No OneTemporary

File Metadata

Created
Mon, Dec 15, 5:48 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/core/aux/graphs_trees_depth.lp b/core/aux/graphs_trees_depth.lp
new file mode 100644
index 0000000..a322358
--- /dev/null
+++ b/core/aux/graphs_trees_depth.lp
@@ -0,0 +1,2 @@
+graphs_tree_depth(X, 0) :- not graphs_tree_depends(X, _); graphs_node(X).
+graphs_tree_depth(X, LEVEL):- LEVEL = #max{L+1, graphs_tree_depth(Y, L): graphs_tree_depth(Y, L), graphs_tree_depends(X, Y)}; graphs_node(X); LEVEL > 0.
\ No newline at end of file
diff --git a/core/control-context-v1.lp b/core/control-context-v1.lp
new file mode 100644
index 0000000..62237fe
--- /dev/null
+++ b/core/control-context-v1.lp
@@ -0,0 +1,24 @@
+ % context propagation
+
+bind_scope_decision(Scope, Fn, Resolution):- cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution), bind_scope(Scope, Resolution).
+bind_scope_decision(Scope, Fn, Resolution):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Fn), cfa_function_specializations(Fn, Resolution), bind_scope(Scope, Resolution).
+
+bind_scope_demand(Scope, FnCallee):- cfa_call(Scope, FnCallee), cfa_function_specializations(FnCallee, _), not bind_scope_decision(Scope, FnCallee, _).
+
+ %demand propagation
+bind_scope_demand(Scope, Subject):- bind_scope_demand(ScopeChild, Subject), cfa_parent(ScopeChild, scope(Scope)).
+bind_scope_demand(Scope, Subject):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Subject), not bind_scope_decision(Scope, Subject, _).
+bind_function_demand(Fn, Subject):- bind_scope_demand(Scope, Subject), cfa_parent(Scope, function(Fn)).
+
+bind_scope(Scope, Context) :- bind_scope(ScopeParent, Context), cfa_parent(Scope, scope(ScopeParent)).
+bind_scope(Scope, Context) :- bind_scope(ScopeParent, Context): cfa_call(ScopeParent, FnCurrent); cfa_call(_, FnCurrent)
+ , cfa_parent(Scope, function(FnCurrent)), bind_scope(_, Context), scope(Scope).
+
+% adhoc classes(unfinished):
+%bind_func(Fn, adhoc_class(Context)) :- bind_func(Fn, adhoc(Context)), bind_scope(Scope, Context), cfa_parent(Scope, function(Fn)).
+
+%scope_parent(Scope, ScopeParent) :- cfa_parent(Scope, scope(ScopeParent)).
+%scope_parent(Scope, ScopeParent2) :- cfa_parent(Scope, scope(ScopeParent)), scope_parent(ScopeParent, ScopeParent2).
+
+%scope_function(Scope, Fn) :- cfa_parent(Scope, function(Fn)).
+%scope_function(Scope, Fn) :- cfa_parent(Scope, scope(ScopeParent)), scope_function(ScopeParent, Fn).
diff --git a/scripts/metatests/context-latecontext3.lp b/core/control-context-v3.lp
similarity index 93%
copy from scripts/metatests/context-latecontext3.lp
copy to core/control-context-v3.lp
index ca81a77..1b651f1 100644
--- a/scripts/metatests/context-latecontext3.lp
+++ b/core/control-context-v3.lp
@@ -1,48 +1,52 @@
%% SCHEMA:
%% specialization(Fn, Scope) - problem of what specialization of Fn should be picked up in Scope.
%% resolution_dependency(Resolution, Dependency) - Dependency is necessary prerequisite for choosing Resolution.
%%
-
+
+true.
+
%nested scope propagation:
bind_scope(Scope, Context, Info) :- bind_scope(ScopeParent, Context, Info), cfa_parent(Scope, scope(ScopeParent)).
%strong/uniform inter-function propagation:
bind_scope(Scope, Context,Info) :- bind_scope(ScopeParent, Context, Info): cfa_call(ScopeParent, FnCurrent); cfa_parent(Scope, function(FnCurrent)); cfa_call(_, FnCurrent); bind_scope(_, Context, Info); scope(Scope).
%weak inter-function propagation
bind_scope(Scope, Context, weak(ScopeParent)):- not bind_scope(Scope, Context, strong), bind_scope(ScopeParent, Context, strong), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
bind_scope(Scope, Context, weak(ScopeParent, Info)):- Info<>strong, not bind_scope(Scope, Context, Info), bind_scope(ScopeParent, Context, Info), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
%make decisions
%%%bind_scope_decision(Scope, loop(Subject), Scope):- cfa_contextloop(Scope, Subject), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).*
%%%bind_scope_decision(Scope, loop(Subject), Scope):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, loop(Subject)), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).
%on-site decision
% ASSERT: ON-SITE DECISION SHOULD BE FIRST CLASS (checks at least one specialization exists)
bind_scope_decision(Scope, Subject, Resolution):- bind_scope(Scope, Resolution, strong), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
bind_scope_decision(ScopeSource, Subject, Resolution):- bind_scope(Scope, Resolution, weak(ScopeSource)), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
bind_scope_decision(ScopeSource, Subject, resolution_dependency(Resolution, Dependency)):- bind_scope(Scope, Resolution, weak(ScopeSource, Dependency)), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
%dependent decisions
bind_scope_demand(Scope, dependency(Subject, Scope)) :- bind_scope_decision(Scope, Subject, resolution_dependency(_, Dependency)).
+bind_scope_demand(ScopeSource, dependency(Subject, ScopeSource)) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
bind_scope_decision(ScopeSource, dependency(Subject, Scope), Dependency) :- Dependency = weak(ScopeSource), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
-bind_scope_demand(ScopeSource, dependency(Subject, ScopeSource)) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
+bind_scope_decision(ScopeSource, dependency(Subject, Scope), resolution_dependency(Dependency, DependencyTail)) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
+
%dependent decision helpers:
scope_dependencies(dependency(Subject, Scope), Dependency) :- bind_scope_decision(Scope, Subject, resolution_dependency(_, Dependency)).
scope_dependencies(dependency(Subject, ScopeSource), DependencyTail) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
%on-site demand
% ASSERT: ON-SITE DEMAND SHOULD BE dependent OF on-site decision (check there are no specializations AT ALL)
%%%bind_scope_demand(Scope, Subject):- cfa_contextloop(Scope, Subject), not bind_scope_decision(Scope, loop(Subject), _).
bind_scope_demand(Scope, Subject):- Subject = specialization(FnCallee, Scope), cfa_call(Scope, FnCallee), cfa_function_specializations(FnCallee, _), not bind_scope_decision(Scope, Subject, _).
%nested scope demand propagation
%ASSERT: NO DECISION CHECKS. because decisions linked to a leaf(function execution sites) scopes
bind_scope_demand(Scope, Subject):- bind_scope_demand(ScopeChild, Subject), cfa_parent(ScopeChild, scope(Scope)).
bind_function_demand(Fn, Subject):- bind_scope_demand(Scope, Subject), cfa_parent(Scope, function(Fn)).
%inter-function propagation demand
bind_scope_demand(Scope, Subject):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Subject), not bind_scope_decision(Scope, Subject, _).
diff --git a/core/dominators.lp b/core/dominators.lp
new file mode 100644
index 0000000..e69de29
diff --git a/core/exploitation.lp b/core/exploitation.lp
new file mode 100644
index 0000000..20f47d5
--- /dev/null
+++ b/core/exploitation.lp
@@ -0,0 +1,12 @@
+expl_sites(Data, Site) :- S=(_, Site); bind(S, exploitation_initialized(file)); bind(S, static(data(Data))).
+expl_sites(Data, Site) :- S=(_, Site); bind(S, exploitation_initialized(file)); bind(S, static(ref(Root))); bind(Root, static(data(Data))).
+
+
+expl_parent(Site, dom(Parent)) :- cfa_forwdom(Parent, range(A, B)); cfa_forwdom(Site, range(A1, B1)); A<A1; B1<B.
+expl_parent(Site, postdom(Parent)) :- cfa_postdom(Parent, range(A, B)); cfa_postdom(Site, range(A1, B1)); A<A1; B1<B.
+expl_resources(Data, dom(Dom)) :- expl_parent(Site, dom(Dom)): expl_sites(Data, Site); expl_sites(Data, _); bind(_, static(data(Data))); cfa_forwdom(Dom, _).
+
+%%
+%% TODO:
+%% 1. (Post)doms are overconstrained and overpessimistic in case when
+%% function used to process different resources depending on particular caller.
diff --git a/core/precompilation.lp b/core/precompilation.lp
new file mode 120000
index 0000000..b21ab11
--- /dev/null
+++ b/core/precompilation.lp
@@ -0,0 +1 @@
+/private/prg/code/xreate/scripts/precompilation-1.lp
\ No newline at end of file
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 1c12f2e..aae16f1 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,16 +1,16 @@
cmake_minimum_required(VERSION 2.8.11)
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -g -Wall -fprofile-arcs -ftest-coverage -O0")
set(CMAKE_BUILD_TYPE Debug)
add_subdirectory(src)
if (BUILD_XREATE_TESTS)
message ("Building xreate tests")
add_subdirectory(tests)
endif ()
if (BUILD_XREATE_SERVER)
message ("Building xreate server")
add_subdirectory(../tools/execution-server execution-server)
endif ()
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 3a28174..b64dbed 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,221 +1,228 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
# BUILD OPTIONS
#======================
set(XREATE_DEFINITIONS
-D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DWITH_THREADS=1
)
add_definitions(${XREATE_DEFINITIONS})
add_compile_options(-Winvalid-pch -std=c++14 -fPIC)
# LLVM
#======================
-find_package(LLVM REQUIRED CONFIG)
+FIND_PACKAGE (LLVM REQUIRED CONFIG PATHS /opt/llvm-3.8.0-0.x86_64/usr/share/llvm/cmake NO_DEFAULT_PATH)
set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-tools")
-include(PCH_GCC4_v2)
+#include(PCH_GCC4_v2)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
-link_directories(${LLVM_LIBRARY_DIRS})
+message ("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
message ("MPATH:" ${CMAKE_MODULE_PATH})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message("LLVM defs: " ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS})
-#llvm_map_components_to_libnames(llvm_libs support core irreader all native nativecodegen)
+llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support)
+message("LLVM libs: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
- clangCodeGen
- clangASTMatchers
- clangQuery
- clangTooling
- clangFrontend
- clangSerialization
- clangDriver
- clangParse
- clangSema
- clangAnalysis
- clangAST
- clangEdit
- clangLex
- clangBasic
+ ${LLVM_LIBRARY_DIRS}/libclangCodeGen.so
+ ${LLVM_LIBRARY_DIRS}/libclangASTMatchers.so
+ ${LLVM_LIBRARY_DIRS}/libclangQuery.so
+ ${LLVM_LIBRARY_DIRS}/libclangTooling.so
+ ${LLVM_LIBRARY_DIRS}/libclangFrontend.so
+ ${LLVM_LIBRARY_DIRS}/libclangSerialization.so
+ ${LLVM_LIBRARY_DIRS}/libclangDriver.so
+ ${LLVM_LIBRARY_DIRS}/libclangParse.so
+ ${LLVM_LIBRARY_DIRS}/libclangSema.so
+ ${LLVM_LIBRARY_DIRS}/libclangAnalysis.so
+ ${LLVM_LIBRARY_DIRS}/libclangAST.so
+ ${LLVM_LIBRARY_DIRS}/libclangEdit.so
+ ${LLVM_LIBRARY_DIRS}/libclangLex.so
+ ${LLVM_LIBRARY_DIRS}/libclangBasic.so
)
#find_package(Clang REQUIRED clangTooling libClang)
message(STATUS "CLANG LIBS: " ${CLANG_LIBS})
# POTASSCO
#======================
-set(POTASSCO_PATH "/opt/potassco/gringo" CACHE PATH "Path to gringo sources")
+set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
+ ${POTASSCO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
+ lp
)
message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS})
link_directories(${LIBCLASP_PATH})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
+
set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
-set(COCO_SOURCE_FILES
- ${COCO_PATH}/Parser.cpp
- ${COCO_PATH}/Scanner.cpp
-)
+set(COCO_SOURCE_FILES
+ ${COCO_PATH}/Parser.cpp
+ ${COCO_PATH}/Scanner.cpp)
+INCLUDE_DIRECTORIES(${COCO_PATH})
-INCLUDE_DIRECTORIES(${COCO_PATH} ./src)
-add_custom_command(OUTPUT COCO_OUTPUT
+add_custom_command(OUTPUT ${COCO_SOURCE_FILES}
COMMAND ${COCO_PATH}/gen-grammar
WORKING_DIRECTORY ${COCO_PATH}
- DEPENDS ${COCO_PATH}/xreate.ATG
+ MAIN_DEPENDENCY ${COCO_PATH}/xreate.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
set(SOURCE_FILES
pass/compilepass.cpp
+
+ ast.cpp
+ ExternLayer.cpp
+ attachments.cpp
+ pass/interpretationpass.cpp
+ compilation/targetinterpretation.cpp
+ analysis/cfagraph.cpp
+ analysis/dfagraph.cpp
+ analysis/aux.cpp
+ compilation/containers.cpp
+ compilation/advanced.cpp
+ compilation/transformations.cpp
+ analysis/DominatorsTreeAnalysisProvider.cpp
+ clasplayer.cpp
compilation/latecontextcompiler2.cpp
+ query/context.cpp
#compilation/latecontextcompiler.cpp
serialization/expressionserializer.cpp
serialization/expressionserializer2.cpp
- query/context.cpp
-
- ast.cpp
- llvmlayer.cpp clasplayer.cpp
-
- utils.cpp
+ llvmlayer.cpp
+ utils.cpp
passmanager.cpp
-
- pass/abstractpass.cpp pass/dfgpass.cpp
- pass/cfgpass.cpp
+ pass/abstractpass.cpp pass/dfapass.cpp
+ pass/cfapass.cpp
pass/loggerpass.cpp
pass/adhocpass.cpp
#pass/rulespass.cpp #
-
- compilation/instr-containers.cpp
-
query/containers.cpp
query/ptrvalid.cpp
-
-
- attachments.cpp
contextrule.cpp
- ExternLayer.cpp
#${POTASSCO_PATH}/app/shared/src/clingocontrol.cc
#${POTASSCO_PATH}/app/pyclingo/src/clingo_lib.cc
)
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES} )
-target_link_libraries(${PROJECT_NAME} ${LIBCLASP_LIBS} ${CLANG_LIBS} tbb)
+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES})
+target_link_libraries(${PROJECT_NAME} ${LIBCLASP_LIBS})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
message("definitions all: " ${DEFINITIONS_ALL})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL})
get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
message("compilations all: " ${COMPILATION_OPTIONS_ALL})
target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES
- LLVM-${LLVM_VERSION}
+SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY
+ INTERFACE_LINK_LIBRARIES ${LLVM_LIBS} ${CLANG_LIBS} tbb
)
#set (LINK_INTERFACE_LIBRARIES "")
# FUNCTION(PREPEND var prefix)
# SET(listVar "")
# FOREACH(f ${ARGN})
# LIST(APPEND listVar "${prefix}/${f}")
# ENDFOREACH(f)
# SET(${var} "${listVar}" PARENT_SCOPE)
# ENDFUNCTION(PREPEND)
#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
#cotire(xreate)
# MACRO (ADD_PCH_RULE _header_filename _src_list)
# SET(_gch_filename "${_header_filename}.gch")
# LIST(APPEND ${_src_list} ${_gch_filename})
# SET (_args ${CMAKE_CXX_FLAGS})
# LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename})
# GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
# foreach (_inc ${DIRINC})
# LIST(APPEND _args "-I" ${_inc})
# endforeach(_inc ${DIRINC})
# SEPARATE_ARGUMENTS(_args)
# add_custom_command(OUTPUT ${_gch_filename}
# COMMAND rm -f ${_gch_filename}
# COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
# DEPENDS ${_header_filename})
# ENDMACRO(ADD_PCH_RULE _header_filename _src_list)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index ed57492..48f3f85 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,285 +1,299 @@
//
// Created by pgess on 4/21/15.
//
#include "ExternLayer.h"
#include <cstdio>
#include <iostream>
#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/Lex/PreprocessorOptions.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
+#include "../../vendors/clang-codegen-private-3.8/CodeGenModule.h"
+
using namespace xreate;
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
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_NAMED);
//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)
- : __datalayout(llvm->module), __llvm(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;
if (linebuf[linelen-1 ] == ' ')
linebuf[linelen-1] = 0;
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;
if (linebuf[linelen-1 ] == ' ')
linebuf[linelen-1] = 0;
if (linelen>=2 && linebuf[0] == '-' && linebuf[1] == 'l'){
libs.push_back(linebuf + 2);
} else {
libs.push_back(linebuf);
}
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 use default include path from 'clang -xc++ -E'
list<string> code;
std::vector<string> args{
"-I/usr/include"
,"-I/usr/local/include"
,"-I/usr/lib/llvm-3.6/lib/clang/3.6.2/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);
__cgo.reset(new CodeGenOptions);
- __datalayout = llvm::DataLayout(ast->getASTContext().getTargetInfo().getTargetDescription());
- __cgm.reset(new CodeGen::CodeGenModule(ast->getASTContext(), *__cgo, *__llvm->module, __datalayout, ast->getASTContext().getDiagnostics()));
+ __llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayoutString());
+
+ std::unique_ptr<clang::HeaderSearchOptions> __hso(new HeaderSearchOptions());
+ std::unique_ptr<clang::PreprocessorOptions> __ppo(new PreprocessorOptions());
+
+ __cgm.reset(new CodeGen::CodeGenModule(
+ ast->getASTContext(),
+
+ *__hso,
+ *__ppo,
+ *__cgo,
+ *__llvm->module,
+ ast->getASTContext().getDiagnostics()));
};
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 __cgm->getTypes().ConvertType(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;
}
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 = __cgm->getTypes().ConvertType(tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
llvm::Function* function = llvm::Function::Create(tyRawFunc, llvm::GlobalValue::ExternalLinkage, name, __llvm->module);
__functions.emplace(name, function);
return function;
}
diff --git a/cpp/src/ExternLayer.h b/cpp/src/ExternLayer.h
index ab41749..a126843 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,55 +1,54 @@
//
// Created by pgess on 4/21/15.
//
#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 "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenModule.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
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;
};
class ExternLayer {
public:
ExternLayer(LLVMLayer* llvm);
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);
void init(const AST* root);
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::CodeGen::CodeGenModule> __cgm;
std::unique_ptr<clang::CodeGenOptions> __cgo;
- llvm::DataLayout __datalayout;
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/DominatorsTreeAnalysisProvider.cpp b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp
new file mode 100644
index 0000000..7d08a2d
--- /dev/null
+++ b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp
@@ -0,0 +1,233 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * File: DominatorsTreeAnalysisProvider.cpp
+ * Author: pgess
+ *
+ * Created on May 13, 2016, 11:39 AM
+ */
+
+#include "analysis/cfagraph.h"
+#include "analysis/DominatorsTreeAnalysisProvider.h"
+
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
+#include "llvm/Support/GenericDomTree.h"
+
+#include <list>
+#include <iostream>
+#include <boost/format.hpp>
+
+using namespace std;
+using namespace xreate;
+using namespace boost;
+using namespace boost::bimaps;
+
+struct ControlFlowTree;
+
+struct Node {
+ ScopePacked scope;
+ ControlFlowTree* tree;
+};
+
+/*
+bool operator !=(const Node& a, const Node& b){
+ return (a.tree != b.tree) || (a.scope != b.scope);
+}
+
+Node& operator++(Node& a){
+ ++a.scope;
+ return a;
+}
+ */
+
+struct ControlFlowTree{
+ typedef bimap<multiset_of<ScopePacked>, multiset_of<ScopePacked>> CHILD_RELATIONS;
+ CHILD_RELATIONS edges;
+ std::vector<Node> nodes;
+ Node* entry = nullptr;
+ size_t size;
+
+ ControlFlowTree(const size_t nodesCount): nodes(nodesCount), size(nodesCount){
+ }
+
+ static ControlFlowTree* build(const ClaspLayer* engine){
+ ControlFlowTree* tree = new ControlFlowTree(engine->getScopesCount());
+
+ xreate::analysis::CFAGraph* graph = engine->dataCFA.get();
+
+ for (const auto& edge: graph->__parentScopeRelations){
+ tree->edges.insert(CHILD_RELATIONS::value_type(edge.second, edge.first));
+ }
+
+ for (const auto& edge: graph->__callRelations){
+ unsigned int calleeFunction = edge.right;
+ ScopePacked caller = edge.left;
+
+ auto range = graph->__parentFunctionRelations.right.equal_range(calleeFunction);
+ for (auto& i=range.first; i!= range.second; ++i){
+ tree->edges.insert(CHILD_RELATIONS::value_type(caller, i->second));
+ }
+ }
+
+ for (size_t i=0; i<tree->size; ++i){
+ tree->nodes[i]= Node{(unsigned int) i, tree};
+ }
+
+ return tree;
+ }
+
+ std::list<unsigned int> getRootFunctions() const{
+ size_t idMax = size;
+ size_t id =0;
+ std::list<unsigned int> results;
+ auto i = edges.right.begin();
+
+ while (id < idMax) {
+ if (i!= edges.right.end() && i->first == id){
+ i = edges.right.upper_bound(i->first);
+
+ } else {
+ results.push_back(id);
+ }
+
+ ++id;
+ }
+
+ return std::move(results);
+ }
+};
+
+namespace llvm {
+ template <> struct GraphTraits<Node*> {
+ typedef Node* nodes_iterator;
+ typedef Node NodeType;
+
+ typedef std::function<Node*(ControlFlowTree::CHILD_RELATIONS::left_value_type)> Transformer;
+ typedef typename boost::iterators::transform_iterator<Transformer, ControlFlowTree::CHILD_RELATIONS::left_iterator> ChildIteratorType;
+
+ static ChildIteratorType child_begin(const nodes_iterator& node) {
+ auto range = node->tree->edges.left.equal_range(node->scope);
+ Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];};
+
+ return boost::make_transform_iterator(range.first, x);
+ }
+
+ static ChildIteratorType child_end(const nodes_iterator& node) {
+ auto range = node->tree->edges.left.equal_range(node->scope);
+ Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];};
+
+ return boost::make_transform_iterator(range.second, x);
+ }
+ };
+
+ template <> struct GraphTraits<Inverse<Node*>> {
+ typedef Node* nodes_iterator;
+ typedef Node NodeType;
+
+ typedef std::function<Node*(ControlFlowTree::CHILD_RELATIONS::right_value_type)> Transformer;
+ typedef typename boost::iterators::transform_iterator<Transformer, ControlFlowTree::CHILD_RELATIONS::right_iterator> ChildIteratorType;
+
+ static ChildIteratorType child_begin(const nodes_iterator& node) {
+ auto range = node->tree->edges.right.equal_range(node->scope);
+ Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];};
+
+ return boost::make_transform_iterator(range.first, x);
+ }
+
+ static ChildIteratorType child_end(const nodes_iterator& node) {
+ auto range = node->tree->edges.right.equal_range(node->scope);
+ Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];};
+
+ return boost::make_transform_iterator(range.second, x);
+ }
+ };
+
+ template <> struct GraphTraits<ControlFlowTree*>: public GraphTraits<Node*> {
+ static NodeType*
+ getEntryNode(ControlFlowTree* F) {
+ if (F->entry) return F->entry;
+
+ list<unsigned int>&& roots = F->getRootFunctions();
+ assert(roots.size()==1);
+
+ return F->entry = &F->nodes[roots.front()];
+ }
+
+ static nodes_iterator nodes_begin(ControlFlowTree* F) { return &F->nodes[0]; }
+ static nodes_iterator nodes_end(ControlFlowTree* F) { return &F->nodes[F->size]; }
+ static size_t size(ControlFlowTree* F) { return F->size; }
+ };
+}
+
+class xreate::DominatorTree: public llvm::DominatorTreeBase<Node> {
+public:
+ DominatorsTreeAnalysisProvider::Dominators dominators;
+
+ DominatorTree(bool isPostDom): llvm::DominatorTreeBase<Node>(isPostDom) {}
+
+ void run(ControlFlowTree& program){
+ recalculate(program);
+
+ //extract dominators info
+ for (auto& entry: DomTreeNodes){
+ if (!entry.getFirst()) continue;
+
+ dominators.emplace(entry.getFirst()->scope, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
+ }
+ }
+
+ void print(std::ostringstream& output, const std::string& atom) const {
+ boost::format formatAtom(atom + "(%1%, range(%2%, %3%)).");
+ for (auto entry: dominators){
+ output << formatAtom % (entry.first) % (entry.second.first) % (entry.second.second)
+ << endl;
+ }
+ }
+};
+
+void
+DominatorsTreeAnalysisProvider::run(const ClaspLayer* engine){
+ boost::scoped_ptr<ControlFlowTree> program(ControlFlowTree::build(engine));
+
+ treeForwardDominators->run(*program);
+ treePostDominators->run(*program);
+}
+
+void
+DominatorsTreeAnalysisProvider::print(std::ostringstream& output) const{
+ treeForwardDominators->print(output, "cfa_forwdom");
+ treePostDominators->print(output, "cfa_postdom");
+}
+
+const DominatorsTreeAnalysisProvider::Dominators&
+DominatorsTreeAnalysisProvider::getForwardDominators() const{
+ return treeForwardDominators->dominators;
+}
+
+const DominatorsTreeAnalysisProvider::Dominators&
+DominatorsTreeAnalysisProvider::getPostDominators() const{
+ return treePostDominators->dominators;
+}
+
+DominatorsTreeAnalysisProvider::DominatorsTreeAnalysisProvider()
+ : treeForwardDominators(new DominatorTree(false))
+ , treePostDominators(new DominatorTree(true))
+{}
+
+DominatorsTreeAnalysisProvider::~DominatorsTreeAnalysisProvider() {}
+
+//void
+//CodeScopesTree::print(){
+// typedef llvm::GraphTraits<Node*> Traits;
+// for (size_t i=0; i<size; ++i){
+//
+// for (auto j = Traits::child_begin(&nodes[i]); j!= Traits::child_end(&nodes[i]); ++j){
+// cout << i << "->" << (*j)->scope << endl;
+// }
+// }
+//}
\ No newline at end of file
diff --git a/cpp/src/analysis/DominatorsTreeAnalysisProvider.h b/cpp/src/analysis/DominatorsTreeAnalysisProvider.h
new file mode 100644
index 0000000..5574891
--- /dev/null
+++ b/cpp/src/analysis/DominatorsTreeAnalysisProvider.h
@@ -0,0 +1,44 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * File: DominatorsTreeAnalysisProvider.h
+ * Author: pgess
+ *
+ * Created on May 13, 2016, 11:39 AM
+ */
+
+#ifndef DOMINATORSTREEANALYSISPROVIDER_H
+#define DOMINATORSTREEANALYSISPROVIDER_H
+
+#include "clasplayer.h"
+#include <boost/smart_ptr/scoped_ptr.hpp>
+
+namespace xreate{
+ class DominatorTree;
+
+ class DominatorsTreeAnalysisProvider: public IAnalysisData {
+ public:
+ typedef std::pair<ScopePacked, ScopePacked> DominatedRange;
+ typedef std::map<ScopePacked, DominatedRange> Dominators;
+
+ DominatorsTreeAnalysisProvider();
+ virtual ~DominatorsTreeAnalysisProvider();
+
+ void run(const ClaspLayer* engine);
+ void print(std::ostringstream& output) const;
+
+ const Dominators& getForwardDominators() const;
+ const Dominators& getPostDominators() const;
+
+ private:
+ boost::scoped_ptr<DominatorTree> treeForwardDominators;
+ boost::scoped_ptr<DominatorTree> treePostDominators;
+ };
+}
+
+#endif /* DOMINATORSTREEANALYSISPROVIDER_H */
+
diff --git a/cpp/src/analysis/aux.cpp b/cpp/src/analysis/aux.cpp
new file mode 100644
index 0000000..6d5192c
--- /dev/null
+++ b/cpp/src/analysis/aux.cpp
@@ -0,0 +1,136 @@
+#include "aux.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;
+}
+
+std::list<std::string>
+compile(const Expression &e){
+ list<string> result;
+
+ switch (e.op) {
+ case Operator::CALL: {
+ assert(e.__state == Expression::COMPOUND);
+
+ 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::NONE: {
+ 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;
+ }
+
+//TODO Null ad hoc ClaspLayer implementation
+// if (e.isNone()){
+// result.push_back(e.__valueS);
+// }
+
+ assert(result.size());
+ 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;
+}
+
+boost::format
+formatSymbol(const SymbolPacked& s){
+ boost::format formatSymbNamed("(%1%, %2%)");
+ boost::format formatSymbAnonymous("(anonym(%1%), %2%)");
+
+ if (!s.categoryTransient){
+ return formatSymbNamed % s.identifier % s.scope;
+ } else {
+ return formatSymbAnonymous % s.identifier % s.scope;
+ }
+}
+
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/aux.h b/cpp/src/analysis/aux.h
new file mode 100644
index 0000000..c8bad41
--- /dev/null
+++ b/cpp/src/analysis/aux.h
@@ -0,0 +1,25 @@
+/*
+ * File: aux.h
+ * Author: pgess
+ *
+ * Created on June 26, 2016, 6:49 PM
+ */
+
+#ifndef AUX_H
+#define AUX_H
+
+#include "ast.h"
+#include "clasplayer.h"
+
+#include <list>
+#include <boost/format.hpp>
+
+namespace xreate { namespace analysis {
+ 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 formatSymbol(const SymbolPacked& s);
+}}
+
+#endif /* AUX_H */
+
diff --git a/cpp/src/analysis/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp
new file mode 100644
index 0000000..be428ed
--- /dev/null
+++ b/cpp/src/analysis/cfagraph.cpp
@@ -0,0 +1,166 @@
+/*
+ * File: CFAGraph.cpp
+ * Author: pgess
+ *
+ * Created on June 27, 2016, 2:09 PM
+ */
+
+#include "analysis/cfagraph.h"
+#include "analysis/aux.h"
+
+using namespace xreate::analysis;
+using namespace std;
+
+void
+CFAGraph::print(std::ostringstream& output) const {
+ const std::string& atomBinding = Config::get("clasp.bindings.function");
+ const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
+
+ //show function tags
+ int counterTags = 0;
+ std::ostringstream bufFunctionNames;
+ boost::format formatFunction("function(%1%).");
+ boost::format formatBind(atomBinding + "(%1%, %2%).");
+ for (auto function: this->__nodesFunction.left) {
+ const auto tags = this->__functionTags.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 functtion tags at all" << endl;
+ }
+
+ //declare scopes
+ boost::format formatScope("scope(0..%1%).");
+ output << formatScope % (__clasp->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;
+ }
+
+ output << endl << "%\t\tStatic analysis: CFA" << endl;
+
+ //parent connections
+ //TOTEST CFG parent function
+ boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
+ for (const auto &relation: this->__parentFunctionRelations) {
+ const string& function = this->__nodesFunction.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->__parentScopeRelations) {
+ 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->__nodesFunction.left.at(relation.right);
+
+ output << formatCall % (scopeFrom) % (functionTo) << endl;
+ }
+
+ //function specializations descrtiption
+ //SECTIONTAG late-context cfa_function_specializations
+ boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
+ const list<ManagedFnPtr>& functions = __clasp->ast->getAllFunctions();
+ for (auto f: functions){
+ if (f->guardContext.isValid()){
+ list<string> guardRaw = xreate::analysis::compile(f->guardContext);
+ assert(guardRaw.size() == 1);
+ output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
+ }
+ }
+}
+
+void
+CFAGraph::addFunctionAnnotations(const std::string& function, const std::map<std::string, Expression>& tags) {
+ unsigned int fid = registerNodeFunction(function);
+
+ for (auto& tag: tags){
+ __functionTags.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& scopeFrom, const std::string& functionTo) {
+ unsigned int idFuncTo = registerNodeFunction(functionTo);
+
+ __callRelations.insert(CALL_RELATIONS::value_type(scopeFrom, idFuncTo));
+}
+
+void
+CFAGraph::addParentConnection(const ScopePacked& scope, const std::string& functionParent){
+ __parentFunctionRelations.insert(PARENT_FUNCTION_RELATIONS::value_type(scope, registerNodeFunction(functionParent)));
+}
+
+void
+CFAGraph::addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent){
+ __parentScopeRelations.emplace(scope, scopeParent);
+}
+
+unsigned int
+CFAGraph::registerNodeFunction(const std::string& fname){
+ auto pos = __nodesFunction.left.insert(make_pair(__nodesFunction.size(), fname));
+
+ return pos.first->first;
+}
diff --git a/cpp/src/analysis/cfagraph.h b/cpp/src/analysis/cfagraph.h
new file mode 100644
index 0000000..a60499a
--- /dev/null
+++ b/cpp/src/analysis/cfagraph.h
@@ -0,0 +1,56 @@
+/*
+ * File: CFAGraph.h
+ * Author: pgess
+ *
+ * Created on June 27, 2016, 2:09 PM
+ */
+
+#ifndef CFAGRAPH_H
+#define CFAGRAPH_H
+
+#include "clasplayer.h"
+
+namespace xreate {namespace analysis {
+
+ class CFAGraph: public IAnalysisData {
+ public:
+ typedef boost::bimap<ScopePacked, boost::bimaps::multiset_of<unsigned int>> PARENT_FUNCTION_RELATIONS;
+ PARENT_FUNCTION_RELATIONS __parentFunctionRelations;
+ std::map<ScopePacked, ScopePacked> __parentScopeRelations;
+
+ 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 > __nodesFunction;
+ std::multimap<unsigned int, Expression> __functionTags;
+ std::multimap<ScopePacked, Expression> __scopeTags;
+ std::multimap<ScopePacked, ContextRule> __contextRules;
+
+ void print(std::ostringstream& output) const;
+ CFAGraph(ClaspLayer* engine): __clasp(engine){}
+
+ void addFunctionAnnotations(const std::string& function, 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& scopeFrom, const std::string& functionTo);
+ void addParentConnection(const ScopePacked& scope, const std::string& functionParent);
+ void addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent);
+ // void addScopeRetIdentifier(const ScopePacked& scope, const SymbolPacked& identifier);
+
+ private:
+ ClaspLayer* __clasp;
+
+ unsigned int registerNodeFunction(const std::string& fname);
+
+ };
+
+}}
+
+#endif /* CFAGRAPH_H */
+
diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp
new file mode 100644
index 0000000..360035b
--- /dev/null
+++ b/cpp/src/analysis/dfagraph.cpp
@@ -0,0 +1,237 @@
+#include "analysis/dfagraph.h"
+#include "analysis/aux.h"
+
+#include <list>
+
+
+using namespace xreate;
+using namespace xreate::analysis;
+using namespace std;
+
+namespace xreate {namespace analysis {
+void
+DFAGraph::print(std::ostringstream& output) const {
+ std::set<SymbolPacked> symbols;
+
+ output << endl << "%\t\tStatic analysis: DFA" << endl;
+
+ std::vector<std::pair<SymbolPacked, SymbolPacked>>::const_iterator i1;
+ std::vector<DFGConnection>::const_iterator i2;
+
+ boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
+ for (i1= this->__edges.begin(), i2 = this->__data.begin(); i1!= this->__edges.end(); ++i1, ++i2 )
+ {
+ string edgeName;
+ switch (*i2)
+ {
+ case DFGConnection::WEAK: edgeName = "weak"; break;
+ case DFGConnection::STRONG: edgeName = "strong"; break;
+ case DFGConnection::PROTOTYPE: edgeName = "proto"; break;
+ }
+
+ output << formatDfaConnection
+ %formatSymbol(i1->first)
+ %formatSymbol(i1->second)
+ %edgeName
+ << " %" <<this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second)
+ <<endl;
+
+ symbols.insert(i1->first);
+ symbols.insert(i1->second);
+ }
+
+ boost::format formatDfaDependency("dfa_dependency(%1%, %2%).");
+ for (auto i= this->__dependencies.begin(); i!= this->__dependencies.end(); ++i){
+ output<<formatDfaDependency
+ %formatSymbol(i->first)
+ %formatSymbol(i->second)
+ << " %"
+ << this->__clasp->getHintForPackedSymbol(i->first) << " - "
+ << this->__clasp->getHintForPackedSymbol(i->second)
+ <<endl;
+ }
+
+ boost::format formatBind("bind(%1%, %2%).");
+ for (const pair<SymbolPacked, Expression>& tag: this->__tags)
+ {
+ for (string variant: xreate::analysis::compile(tag.second)) {
+ output << formatBind
+ % formatSymbol(tag.first)
+ % (variant)
+ << "%" << this->__clasp->getHintForPackedSymbol(tag.first)
+ << endl;
+ }
+
+ symbols.insert(tag.first);
+ }
+
+ for (const SymbolPacked& s: symbols)
+ {
+ output << "v(" << formatSymbol(s) << ")."
+ << " %" << this->__clasp->getHintForPackedSymbol(s)
+ <<endl;
+ }
+}
+
+class VisitorAddTag: public boost::static_visitor<> {
+ public:
+ void operator()(const SymbolPacked& symbol){
+ __graph->__tags.emplace(symbol, move(__tag));
+ }
+
+ void operator()(SymbolTransient& symbol){
+ symbol.tags.push_back(move(__tag));
+ }
+
+ void operator()(const SymbolInvalid& symbol){
+ assert(false && "Undefined behaviour");
+ }
+
+ VisitorAddTag(DFAGraph* const dfagraph, Expression&& tag):
+ __graph(dfagraph), __tag(tag) {}
+
+ private:
+ DFAGraph* const __graph;
+ Expression __tag;
+};
+
+class VisitorAddLink: public boost::static_visitor<> {
+public:
+ void operator()(const SymbolPacked& nodeFrom){
+ if (!__graph->isConnected(__nodeTo, nodeFrom))
+ {
+ __graph->__edges.emplace_back(__nodeTo, nodeFrom);
+ __graph->__data.push_back(__link);
+
+ DFAGraph::EdgeId eid = __graph->__edges.size()-1;
+ __graph->__outEdges.emplace(nodeFrom, eid);
+ }
+ }
+
+ void operator()(const SymbolTransient& symbolFrom){
+ switch (__link){
+ case DFGConnection::WEAK: {
+ //virtual symbol to hold transient annotations
+ SymbolPacked symbPivot = __graph->createAnonymousSymbol(symbolFrom.scope);
+
+ __graph->addConnection(symbPivot, symbolFrom, DFGConnection::STRONG);
+ __graph->addConnection(__nodeTo, symbPivot, DFGConnection::WEAK);
+ break;
+ }
+
+ case DFGConnection::STRONG: {
+ for (const Expression& tag: symbolFrom.tags){
+ __graph->__tags.emplace(__nodeTo, tag);
+ }
+ break;
+ }
+
+ default:
+ assert(false && "Undefined behavior");
+ }
+ }
+
+ void operator()(const SymbolInvalid&){
+ if (__link == DFGConnection::STRONG) return;
+ if (__link == DFGConnection::WEAK) return;
+
+ assert(false && "Undefined behavior");
+ }
+
+ VisitorAddLink(DFAGraph* const dfagraph, const SymbolPacked& nodeTo, DFGConnection link):
+ __graph(dfagraph), __nodeTo(nodeTo), __link(link) {}
+
+private:
+ DFAGraph* const __graph;
+ SymbolPacked __nodeTo;
+ DFGConnection __link;
+};
+
+class VisitorGetDependencyConnection: public boost::static_visitor<list<SymbolPacked>> {
+public:
+ list<SymbolPacked>
+ operator()(const SymbolPacked& nodeFrom){
+ return {nodeFrom};
+ }
+
+ list<SymbolPacked>
+ operator()(const SymbolTransient& nodeFrom){
+ return nodeFrom.dependencies;
+ }
+
+ list<SymbolPacked>
+ operator()(const SymbolInvalid&){
+ assert(false && "Undefined behavior");
+ }
+
+ VisitorGetDependencyConnection(DFAGraph* const g): graph(g){}
+ DFAGraph* const graph;
+};
+
+class VisitorSetDependencyConnection: public boost::static_visitor<> {
+public:
+ void operator()(SymbolPacked& nodeTo){
+ VisitorGetDependencyConnection visitorGetDepenencies(graph);
+ auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
+
+ for (const SymbolPacked& dep: deps){
+ graph->__dependencies.emplace(nodeTo, dep);
+ }
+ }
+
+ void operator()(SymbolTransient& nodeTo){
+ VisitorGetDependencyConnection visitorGetDepenencies(graph);
+ auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
+
+ for (const SymbolPacked& dep: deps){
+ nodeTo.dependencies.push_back(dep);
+ }
+ }
+
+ void operator()(SymbolInvalid&){
+ assert(false && "Undefined behavior");
+ }
+
+ VisitorSetDependencyConnection(DFAGraph* const g, SymbolNode s): graph(g), nodeFrom(s){}
+ DFAGraph* const graph;
+ SymbolNode nodeFrom;
+};
+
+bool
+DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom)
+{
+ auto range = __outEdges.equal_range(identifierFrom);
+
+ for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
+ {
+ if (__edges[edge->second].second == identifierTo)
+ return true;
+ }
+
+ return false;
+}
+
+void
+DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
+ VisitorAddLink visitor(this, nodeTo, link);
+ boost::apply_visitor(visitor, nodeFrom);
+}
+
+void
+DFAGraph::addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom){
+ VisitorSetDependencyConnection visitor(this, identifierFrom);
+ boost::apply_visitor(visitor, identifierTo);
+}
+
+void
+DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) {
+ VisitorAddTag visitor(this, move(tag));
+ boost::apply_visitor(visitor, node);
+}
+
+SymbolPacked
+DFAGraph::createAnonymousSymbol(const ScopePacked& scope){
+ return SymbolPacked{__countAnonymousSymbols++, scope, true};
+}
+
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/dfagraph.h b/cpp/src/analysis/dfagraph.h
new file mode 100644
index 0000000..374ab14
--- /dev/null
+++ b/cpp/src/analysis/dfagraph.h
@@ -0,0 +1,57 @@
+/*
+ * File: dfa.h
+ * Author: pgess
+ *
+ * Created on June 27, 2016, 1:50 PM
+ */
+
+#ifndef DFA_H
+#define DFA_H
+
+#include "clasplayer.h"
+
+namespace xreate {namespace analysis {
+
+ struct SymbolTransient {
+ std::list<Expression> tags;
+ ScopePacked scope;
+ std::list<SymbolPacked> dependencies;
+ };
+
+ struct SymbolInvalid { };
+
+ typedef boost::variant<SymbolInvalid, SymbolTransient, xreate::SymbolPacked> SymbolNode;
+
+ class DFAGraph: public IAnalysisData{
+ friend class VisitorAddTag;
+ friend class VisitorAddLink;
+ friend class VisitorGetDependencyConnection;
+ friend class VisitorSetDependencyConnection;
+
+
+ public:
+ DFAGraph(ClaspLayer* engine): __clasp(engine){}
+
+ SymbolPacked createAnonymousSymbol(const ScopePacked& scope);
+ void addAnnotation(SymbolNode& identifier, Expression&& tag);
+ void addConnection(const SymbolPacked& identifierTo, const SymbolNode& identifierFrom, DFGConnection link);
+ void addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom);
+ bool isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom);
+
+ void print(std::ostringstream& output) const;
+
+ private:
+ typedef unsigned int EdgeId;
+ std::vector<std::pair<SymbolPacked, SymbolPacked>> __edges;
+ std::multimap<SymbolPacked, EdgeId> __outEdges;
+ std::vector<DFGConnection> __data;
+ std::multimap<SymbolPacked, Expression> __tags;
+ std::multimap<SymbolPacked, SymbolPacked> __dependencies;
+
+ unsigned int __countAnonymousSymbols=0;
+ ClaspLayer* __clasp;
+ };
+}}
+
+#endif /* DFA_H */
+
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 6d5f2ad..1552a18 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,701 +1,774 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <clasplayer.h>
using namespace std;
namespace xreate{
+class ExpressionHints{
+public:
+ static bool
+ isStringValueValid(const Expression& e){
+ switch (e.__state){
+ case Expression::INVALID:
+ case Expression::VARIANT:
+ 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:
+ case Operator::INDEX:
+ return true;
+
+ default: return false;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ static bool
+ isDoubleValueValid(const Expression& e){
+ switch (e.__state){
+ case Expression::NUMBER:
+ return true;
+
+ case Expression::INVALID:
+ case Expression::VARIANT:
+ assert(false);
+
+ case Expression::IDENT:
+ case Expression::STRING:
+ case Expression::COMPOUND:
+ case Expression::BINDING:
+ 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::ARRAY:
{
assert(t.__operands.size()==1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, t.__size));
}
case TypeOperator::STRUCT:
{
assert(t.__operands.size());
std::vector<TypeAnnotation>&& pack = expandOperands(t.__operands);
auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack));
tnew.fields = t.fields;
return ExpandedType(move(tnew));
};
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:
{
std::string alias = t.__valueCustom;
/*
if (signatures.count(alias)) {
return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
}
signatures[alias].emplace(t);
*/
//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::STRUCT);
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::TUPLE: {
assert(t.__operands.size());
std::vector<TypeAnnotation> pack;
pack.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation& t){
return expandType(t);
});
return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
}
case TypeOperator::VARIANT: {
return ExpandedType(TypeAnnotation(t));
}
case TypeOperator::NONE: {
return ExpandedType(TypeAnnotation(t));
}
default:
assert(false);
}
assert(false);
return ExpandedType(TypeAnnotation());
}
};
TypeAnnotation::TypeAnnotation()
{
}
TypeAnnotation::TypeAnnotation(const Atom<Type_t> &typ)
: __value(typ.get())
{
;
}
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::ARRAY, {typ})
{
__size=size;
}
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(); });
}
Expression::Expression(const Atom<Number_t>& number)
: __state(NUMBER), op(Operator::NONE), __valueD(number.get())
{
}
Expression::Expression(const Atom<String_t>& a)
: __state(STRING), op(Operator::NONE), __valueS(a.get())
{
}
Expression::Expression(const Atom<Identifier_t> &ident)
: __state(IDENT), op(Operator::NONE), __valueS(ident.get())
{
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: __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::NONE:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg)
{
operands.push_back(arg);
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params)
{
addBindings(params.begin(), params.end());
}
void
-Expression::bindType(TypeAnnotation&& t)
+Expression::bindType(TypeAnnotation t)
{
- type = 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);
+}
+
Expression::Expression()
: __state(INVALID), op(Operator::NONE)
{}
+bool
+Expression::operator==(const Expression& other) const{
+ assert(!this->blocks.size());
+ assert(!other.blocks.size());
+
+ 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->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;
+ }
+
+ return true;
+}
+
AST::AST()
{
}
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){
+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(), t);
+ __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);
+ 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::getFunctionVariants(const std::string& name) const{
auto functions = __indexFunctions.equal_range(name);
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);}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const
{
return TypesResolver(this)(t);
}
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));
}
void
AST::recognizeVariantIdentifier(Expression& identifier){
+
+// TODO get rid of findSymbol. Determine symbol while AST parsing. Re-find symbols not found while first pass.
+// * move to codescope
+// * use findSymbol to find Symbol
+// * register var as alias to
+// * ident __doubleValue holds VID of an alias
+
assert(identifier.__state == Expression::IDENT);
std::string name = identifier.getValueString();
if (__dictVariants.count(name)){
auto record = __dictVariants.at(name);
const TypeAnnotation& typ = record.first;
identifier.__state = Expression::VARIANT;
identifier.setValueDouble(record.second);
identifier.type = typ;
}
}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0))
{
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod)
{
- __tags.emplace_back(tag, mod);
+ string name = tag.getValueString();
+ __tags.emplace(move(name), move(tag));
}
-const std::vector<Tag>&
-Function::getAnnotations() const
+const std::map<std::string, Expression>&
+Function::getTags() const
{
return __tags;
}
CodeScope*
Function::getEntryScope() const
{
return __entry;
}
void
-CodeScope::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
-{
- registerVar(std::move(const_cast<std::string&>(name.get())), std::move(typ));
- __args.push_back(name.get());
-}
-
- ;
-
-void
-Function::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
+Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument)
{
- __entry->addArg(move(name), move(typ));
+ __entry->addBinding(move(name), move(argument));
}
void
Function::setReturnType(const TypeAnnotation &rtyp)
{
- __entry->__definitions[0] = rtyp;
+ __entry->__declarations[0].type = rtyp;
}
const std::string&
Function::getName() const
{
return __name;
}
+Symbol
+CodeScope::registerIdentifier(Atom <Identifier_t> &&name)
+{
+ __identifiers.emplace(name.get(), ++__vCounter);
+ return {__vCounter, this};
+}
+
+void
+CodeScope::addBinding(Atom <Identifier_t>&& name, Expression&& argument)
+{
+ __bindings.push_back(name.get());
+ Symbol binding = registerIdentifier(move(name));
+ argument.__state = Expression::BINDING;
+ __declarations[binding.identifier] = move(argument);
+}
+
+void
+CodeScope::addDeclaration(Atom <Identifier_t>&& name, Expression&& body)
+{
+ Symbol s = registerIdentifier(move(name));
+ __declarations[s.identifier] = move(body);
+}
+
CodeScope::CodeScope(CodeScope* parent)
:__parent(parent)
{}
CodeScope::~CodeScope()
{}
-VID
-CodeScope::registerVar(std::string&& name, TypeAnnotation &&typ)
-{
- __vartable[name] = ++__vCounter;
- __definitions[__vCounter] = typ;
- return __vCounter;
-}
-void
-CodeScope::addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body)
-{
- VID id = registerVar(std::move(const_cast<string&>(name.get())), move(typ));
- __declarations[id] = body;
-}
+
void
CodeScope::setBody(const Expression &body)
{
__body = body;
}
-TypeAnnotation&
-CodeScope::findDefinition(const Symbol& symbol)
-{
- CodeScope* self = symbol.scope;
- assert(self->__definitions.count(symbol.identifier));
- return self->__definitions[symbol.identifier];
-}
-
-//TODO get rid of findSymbol. Determine symbol while AST parsing. Refind symbols not found while first pass.
Symbol
CodeScope::findSymbol(const std::string &name)
{
- //search var in current block
- if (__vartable.count(name))
+ //search identifier in the current block
+ if (__identifiers.count(name))
{
- VID vId = __vartable.at(name);
+ VID vId = __identifiers.at(name);
Symbol result{vId, this};
return result;
}
- //search in parent scope
+ //search in the parent scope
if (__parent)
{
return __parent->findSymbol(name);
}
//exception: Ident not found
std::cout << "Unknown symbol: "<< name << std::endl;
assert(false && "Symbol not found");
}
-bool
-CodeScope:: hasDeclaration(const Symbol& symbol)
-{
- CodeScope* self = symbol.scope;
- return (self->__declarations.count(symbol.identifier));
-}
-
const Expression&
CodeScope::findDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
-
- if (! self->__declarations.count(symbol.identifier))
- {
- // no declaration exists
- assert(false);
- }
-
return self->__declarations[symbol.identifier];
}
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(ClaspLayer& layer)
{
//TODO restore addRuleWarning
//layer.addRuleWarning(*this);
}
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);
}
}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 748048c..fbc2eb4 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,540 +1,561 @@
#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 "attachments.h"
#include "utils.h"
#include <algorithm>
-namespace llvm{
+namespace llvm {
class Value;
}
namespace xreate {
-struct String_t{};
-struct Identifier_t {};
-struct Number_t {};
-struct Type_t {};
+ struct String_t {
+ };
-template<typename A>
-class Atom {};
+ struct Identifier_t {
+ };
-//DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
-template<> class Atom<Identifier_t>
-{
-public:
- Atom(const std::wstring& value)
- {
- char buffer[32];
- wcstombs(buffer, value.c_str(), 32);
+ struct Number_t {
+ };
- __value = buffer;
- }
- Atom(std::string && name): __value(name) {}
+ struct Type_t {
+ };
- const std::string& get() const{return __value; }
-private:
- std::string __value;
-};
+ template<typename A>
+ class Atom {
+ };
-template<> class Atom<Number_t>
-{
-public:
- Atom(wchar_t* value)
- {
- __value = wcstol(value, 0, 10);
- }
+ //DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
- Atom(int value)
- : __value(value)
- {}
- double get()const {return __value; }
-private:
- double __value;
-};
-
-template<> class Atom<String_t>
-{
-public:
- Atom(const std::wstring& value){
- assert(value.size());
- __value = std::string(++value.begin(), --value.end());
- }
+ template<> class Atom<Identifier_t> {
+ public:
- const std::string& get() const {return __value; }
+ Atom(const std::wstring& value) {
+ char buffer[32];
+ wcstombs(buffer, value.c_str(), 32);
-private:
- std::string __value;
-};
+ __value = buffer;
+ }
-enum class TypePrimitive {Bool, Int, Float, Num, String, I32, I8};
+ Atom(std::string && name) : __value(name) {
+ }
-template<> class Atom<Type_t>
-{
-public:
- Atom(wchar_t* value)
- {
- char buffer_[32];
- wcstombs(buffer_, value, 32);
- std::string buffer(buffer_);
-
- if (buffer=="bool"){
- __value = TypePrimitive ::Bool;
- } else if (buffer=="int") {
- __value = TypePrimitive::Int;
- } else if (buffer=="float") {
- __value = TypePrimitive::Float;
- } else if (buffer=="num") {
- __value = TypePrimitive::Num;
- } else if (buffer=="string") {
- __value = TypePrimitive::String;
+ const std::string& get() const {
+ return __value;
}
- }
+ private:
+ std::string __value;
+ };
- Atom()
- {
- }
+ template<> class Atom<Number_t> {
+ public:
- TypePrimitive get() const
- {
- return __value;
- }
+ Atom(wchar_t* value) {
+ __value = wcstol(value, 0, 10);
+ }
-private:
- TypePrimitive __value;
-};
+ Atom(int value)
+ : __value(value) {
+ }
-typedef Atom<Type_t> TypeAtom;
+ double get()const {
+ return __value;
+ }
+ private:
+ double __value;
+ };
+ template<> class Atom<String_t> {
+ public:
+
+ Atom(const std::wstring& value) {
+ assert(value.size());
+ __value = std::string(++value.begin(), --value.end());
+ }
-enum class TypeOperator{NONE, CALL, CUSTOM, VARIANT, ARRAY, TUPLE, STRUCT, ACCESS, LINK};
-struct llvm_array_tag {}; struct struct_tag{};
+ const std::string& get() const {
+ return __value;
+ }
+
+ private:
+ std::string __value;
+ };
+
+ enum class TypePrimitive {
+ Bool, Num, Int, I32, I8, Float, String,
+ };
+
+ template<> class Atom<Type_t> {
+ public:
+
+ Atom(wchar_t* value) {
+ char buffer_[32];
+ wcstombs(buffer_, value, 32);
+ std::string buffer(buffer_);
+
+ if (buffer == "bool") {
+ __value = TypePrimitive::Bool;
+ } else if (buffer == "num") {
+ __value = TypePrimitive::Num;
+ } else if (buffer == "int") {
+ __value = TypePrimitive::Int;
+ } else if (buffer == "i8") {
+ __value = TypePrimitive::I8;
+ } else if (buffer == "i32") {
+ __value = TypePrimitive::I32;
+ } else if (buffer == "float") {
+ __value = TypePrimitive::Float;
+
+ } else if (buffer == "string") {
+ __value = TypePrimitive::String;
+ }
+ }
+
+ Atom() {
+ }
+
+ TypePrimitive get() const {
+ return __value;
+ }
+
+ private:
+ TypePrimitive __value;
+ };
+
+ typedef Atom<Type_t> TypeAtom;
+
+ enum class TypeOperator {
+ NONE, CALL, CUSTOM, VARIANT, ARRAY, TUPLE, STRUCT, ACCESS, LINK
+ };
+
+ struct llvm_array_tag {
+ };
+
+ struct struct_tag {
+ };
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
-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>);
-
-
- 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
-{
-ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, LOOP_CONTEXT, INDEX, IF, SWITCH, SWITCH_ADHOC, CASE, CASE_DEFAULT, LOGIC_AND, ADHOC, CONTEXT_RULE, SEQUENCE
-};
-
-class Function;
-class AST;
-class CodeScope;
-class MetaRuleAbstract;
-
-template<class Target>
-struct ManagedPtr
-{
- static ManagedPtr<Target> Invalid(){
- return ManagedPtr<Target>();
- }
- ManagedPtr(): __storage(0) {}
+ class TypeAnnotation {
+ public:
+ TypeAnnotation();
+ TypeAnnotation(const Atom<Type_t>& typ);
+ TypeAnnotation(TypePrimitive typ);
+ TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
- ManagedPtr(unsigned int id, const std::vector<Target*>* storage)
- : __id(id), __storage(storage)
- {}
+ 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>);
- Target&
- operator*() const
- {
- assert(isValid() && "Invalid Ptr");
- return *__storage->at(__id);
- }
- void operator=(const ManagedPtr<Target>& other)
- {
- __id = other.__id;
- __storage = other.__storage;
- }
+ TypeOperator __operator = TypeOperator::NONE;
- bool
- operator == (const ManagedPtr<Target>& other)
- {
- return isValid() && (__id == other.__id);
- }
+ std::vector<TypeAnnotation> __operands;
+ TypePrimitive __value;
+ std::string __valueCustom;
+ int conjuctionId = -1; //conjunction point id (relevant for recursive types)
- Target*
- operator->() const noexcept
- {
- assert(isValid() && "Invalid Ptr");
- return __storage->at(__id);
- }
+ uint64_t __size = 0;
+ std::vector<std::string> fields;
+ std::vector<std::string> bindings;
+ private:
+ };
- inline bool isValid() const
- {
- return (__storage) && (0 <= __id) && (__id < __storage->size());
- }
+ enum class Operator {
+ ADD, SUB, MUL, DIV, EQU, NE, NEG, LSS, LSE, GTR, GTE, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, FOLD_INF, LOOP_CONTEXT, INDEX, IF, SWITCH, SWITCH_ADHOC, CASE, CASE_DEFAULT, LOGIC_AND, ADHOC, CONTEXT_RULE, SEQUENCE
+ };
- inline operator bool() const {
- return isValid();
- }
+ class Function;
+ class AST;
+ class CodeScope;
+ class MetaRuleAbstract;
- ManagedPtr<Target>& operator++()
- {
- ++__id;
- return *this;
- }
+ template<class Target>
+ struct ManagedPtr {
- inline unsigned int id() const
- {
- return __id;
- }
+ static ManagedPtr<Target> Invalid() {
+ return ManagedPtr<Target>();
+ }
-private:
- unsigned int __id =0;
- const std::vector<Target*> * __storage=0;
-};
-
-typedef ManagedPtr<Function> ManagedFnPtr;
-typedef ManagedPtr<CodeScope> ManagedScpPtr;
-typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
-const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
-
-struct Expression
-{
- friend class CodeScope;
- friend class ClaspLayer;
- friend class CFGPass;
-
- 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);
+ ManagedPtr() : __storage(0) {
+ }
- template<class InputIt>
- void addBindings(InputIt paramsBegin, InputIt paramsEnd);
-
- 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;
-
- enum {INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT} __state = INVALID;
- Operator op;
- std::vector<std::string> bindings;
- std::map<std::string, size_t> __indexBindings;
- std::vector<Expression> operands;
- TypeAnnotation type;
-
- std::map<std::string, Expression> tags;
- std::list<CodeScope*> blocks;
-private:
- std::string __valueS;
- double __valueD;
-
-
-};
-
-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;
- });
-}
+ ManagedPtr(unsigned int id, const std::vector<Target*>* storage)
+ : __id(id), __storage(storage) {
+ }
+
+ Target&
+ operator*() const {
+ assert(isValid() && "Invalid Ptr");
+ return *__storage->at(__id);
+ }
+
+ void operator=(const ManagedPtr<Target>& other) {
+ __id = other.__id;
+ __storage = other.__storage;
+ }
+
+ bool
+ operator==(const ManagedPtr<Target>& other) {
+ return isValid() && (__id == other.__id);
+ }
-typedef std::list<Expression> ExpressionList;
-enum class TagModifier
-{NONE, ASSERT, REQUIRE};
+ Target*
+ operator->() const noexcept {
+ assert(isValid() && "Invalid Ptr");
+ return __storage->at(__id);
+ }
+
+ inline bool isValid() const {
+ return (__storage) && (0 <= __id) && (__id < __storage->size());
+ }
+
+ inline operator bool() const {
+ return isValid();
+ }
-enum class DomainAnnotation
-{FUNCTION, VARIABLE};
+ ManagedPtr<Target>& operator++() {
+ ++__id;
+ return *this;
+ }
+
+ inline unsigned int id() const {
+ return __id;
+ }
-class RuleArguments: public std::vector<std::pair<std::string, DomainAnnotation>>
-{
-public:
- void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
-};
+ private:
+ unsigned int __id = 0;
+ const std::vector<Target*> * __storage = 0;
+ };
+
+ typedef ManagedPtr<Function> ManagedFnPtr;
+ typedef ManagedPtr<CodeScope> ManagedScpPtr;
+ typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
+ const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
+
+ //To update ExpressionHints in case of any changes
+ struct Expression {
+ friend class CodeScope;
+ friend class ClaspLayer;
+ 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 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;
+
+ enum {
+ INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT, BINDING
+ } __state = INVALID;
+ Operator op;
+ std::vector<std::string> bindings;
+ std::map<std::string, size_t> __indexBindings;
+ std::vector<Expression> operands;
+ TypeAnnotation type;
+
+ mutable std::map<std::string, Expression> tags;
+ mutable Attachments tagsInternal;
+ std::list<CodeScope*> blocks;
+
+ private:
+ std::string __valueS;
+ double __valueD;
+ };
+
+ 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;
+ });
+ }
-class RuleGuards: public std::vector<Expression>
-{
-public:
- void add(Expression&& e);
-};
+ typedef std::list<Expression> ExpressionList;
+ enum class TagModifier {
+ NONE, ASSERT, REQUIRE
+ };
-class ClaspLayer;
-class LLVMLayer;
+ 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 MetaRuleAbstract
-{
-public:
- MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
- virtual ~MetaRuleAbstract();
- virtual void compile(ClaspLayer& layer) =0;
-protected:
- RuleArguments __args;
- RuleGuards __guards;
-};
+ class RuleGuards : public std::vector<Expression> {
+ public:
+ void add(Expression&& e);
+ };
-class RuleWarning: public MetaRuleAbstract
-{
- friend class ClaspLayer;
-public:
- RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
- virtual void compile(ClaspLayer& layer);
- ~RuleWarning();
-private:
- std::string __message;
- Expression __condition;
-};
+ class ClaspLayer;
+ class LLVMLayer;
-typedef unsigned int VID;
+ class MetaRuleAbstract {
+ public:
+ MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
+ virtual ~MetaRuleAbstract();
+ virtual void compile(ClaspLayer& layer) = 0;
+ protected:
+ RuleArguments __args;
+ RuleGuards __guards;
+ };
+ class RuleWarning : public MetaRuleAbstract {
+ friend class ClaspLayer;
+ public:
+ RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
+ virtual void compile(ClaspLayer& layer);
+ ~RuleWarning();
+ private:
+ std::string __message;
+ Expression __condition;
+ };
-/*
-class Expression: ExpressionAbstract
-{
- friend class CFGPass;
+ typedef unsigned int VID;
-public:
- llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
-};
-*/
+ /*
+ class Expression: ExpressionAbstract
+ {
+ friend class CFGPass;
-typedef std::pair<VID, TypeAnnotation> VariableDefinition;
-typedef std::pair<VID, Expression> VariableDeclaration;
+ public:
+ llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
+ };
+ */
-typedef std::pair<Expression, TagModifier> Tag;
-struct Symbol
-{
- VID identifier;
- CodeScope * scope;
-};
+ typedef std::pair<Expression, TagModifier> Tag;
-struct SymbolTags_t{};
+ struct Symbol {
+ VID identifier;
+ CodeScope * scope;
+ };
-template<>
-struct AttachmentsDict<SymbolTags_t> {
- typedef std::map<std::string, Expression> Data;
- static const unsigned int key = 2;
-};
+ bool operator<(const Symbol& s1, const Symbol& s2);
+ bool operator==(const Symbol& s1, const Symbol& s2);
-bool operator< (const Symbol& s1, const Symbol& s2);
-bool operator== (const Symbol& s1, const Symbol& s2);
+ class CodeScope {
+ friend class Function;
+ friend class PassManager;
-class CodeScope
-{
- friend class Function;
- friend class PassManager;
+ public:
+ CodeScope(CodeScope* parent = 0);
+ void setBody(const Expression& body);
+ void addDeclaration(Atom <Identifier_t>&& name, Expression&& body);
+ void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
+ Symbol findSymbol(const std::string &name);
+ static const Expression& findDeclaration(const Symbol& symbol);
-public:
- CodeScope(CodeScope* parent=0);
- void setBody(const Expression& body);
- void addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body);
+ ~CodeScope();
- void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
+ std::vector<std::string> __bindings;
+ Expression __body; //TODO move __body to __declarations[0]
+ std::map<std::string, VID> __identifiers;
+ /**
+ * definition of return type has variable index Zero(0)
+ */
+ //TODO move __definitions to SymbolsAttachments data
+ std::unordered_map<VID, Expression> __declarations;
+ std::vector<Expression> tags;
+ std::vector<Expression> contextRules;
+
+ private:
+ VID __vCounter = 0;
+ CodeScope* __parent;
+
+ Symbol registerIdentifier(Atom <Identifier_t>&& name);
+ };
- //TODO exclude forceCompile partz
- Symbol findSymbol(const std::string &name);
- static const Expression& findDeclaration(const Symbol& symbol);
- static TypeAnnotation& findDefinition(const Symbol& symbol);
- static bool hasDeclaration(const Symbol& symbol);
+ class Function {
+ friend class Expression;
+ friend class CodeScope;
+ friend class AST;
- ~CodeScope();
+ public:
+ Function(const Atom<Identifier_t>& name);
- std::vector<std::string> __args;
- Expression __body; //TODO move __body to __declarations[0]
+ void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
+ void addTag(Expression&& tag, const TagModifier mod);
- SymbolAttachments attachments;
- std::map<std::string, VID> __vartable;
- /**
- * definition of return type has variable index Zero(0)
- */
- //TODO move __definitions to SymbolsAttachments data
- std::unordered_map<VariableDefinition::first_type, VariableDefinition::second_type> __definitions;
- std::unordered_map<VariableDeclaration::first_type, VariableDeclaration::second_type> __declarations;
- std::vector<Expression> tags;
- std::vector<Expression> contextRules;
-protected:
- VID __vCounter=1;
- CodeScope* __parent;
- std::list<CodeScope*> __storage;
- VID registerVar(std::string&& name, TypeAnnotation &&typ);
-};
+ void setReturnType(const TypeAnnotation& rtyp);
-class Function
-{
- friend class Expression;
- friend class CodeScope;
- friend class AST;
+ 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
-public:
- Function(const Atom<Identifier_t>& name);
+ Expression guardContext;
+ private:
- void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
- void addTag(Expression&& tag, const TagModifier mod);
+ std::map<std::string, Expression> __tags;
+ };
- void setReturnType(const TypeAnnotation& rtyp);
- const std::string& getName() const;
- const std::vector<Tag>& getAnnotations() const;
- CodeScope* getEntryScope() const;
- CodeScope* __entry;
- std::string __name;
- bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
+ class ExternData;
- Expression guardContext;
-private:
+ struct ExternEntry {
+ std::string package;
+ std::vector<std::string> headers;
+ };
- std::vector<Tag> __tags;
-};
+ typedef Expanded<TypeAnnotation> ExpandedType;
+ enum ASTInterface {
+ CFA, DFA, Extern, Adhoc
+ };
-class ExternData;
+ struct FunctionSpecialization {
+ std::string guard;
+ size_t id;
+ };
-struct ExternEntry {
- std::string package;
- std::vector<std::string> headers;
-};
+ struct FunctionSpecializationQuery {
+ std::unordered_set<std::string> context;
+ };
-typedef Expanded<TypeAnnotation> ExpandedType;
+ template<>
+ struct AttachmentsStorage<Symbol> {
-enum ASTInterface {
- CFA, DFA, Extern, Adhoc
-};
+ static Attachments*
+ get(const Symbol& s) {
+ return &s.scope->findDeclaration(s).tagsInternal;
+ }
+ };
-struct FunctionSpecialization {
- std::string guard;
- size_t id;
-};
+ template<>
+ struct AttachmentsStorage<Expression> {
-struct FunctionSpecializationQuery {
- std::unordered_set<std::string> context;
-};
+ static Attachments*
+ get(const Expression& e) {
+ return &e.tagsInternal;
+ }
+ };
-class AST
-{
-public:
- AST();
+ class AST {
+ public:
+ AST();
- //TASK extern and DFA interfaces move into addInterfaceData
+ //TASK extern and DFA interfaces move into addInterfaceData
/**
* DFA Interface
*/
- void addDFAData(Expression&& data);
+ void addDFAData(Expression&& data);
/**
* Extern Interface
*/
- void addExternData(ExternData&& data);
+ void addExternData(ExternData&& data);
- void addInterfaceData(const ASTInterface& interface, Expression&& data );
- void add(Function* f);
+ void addInterfaceData(const ASTInterface& interface, Expression&& data);
+ void add(Function* f);
- void add(MetaRuleAbstract* r);
- ManagedScpPtr add(CodeScope* scope);
+ void add(MetaRuleAbstract* r);
+ ManagedScpPtr add(CodeScope* scope);
- std::string getModuleName();
- ManagedPtr<Function> findFunction(const std::string& name);
+ std::string getModuleName();
+ ManagedPtr<Function> findFunction(const std::string& name);
- typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
- std::list<ManagedFnPtr> getAllFunctions() const;
- std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
+ typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
+ std::list<ManagedFnPtr> getAllFunctions() const;
+ std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
- template<class Target>
- ManagedPtr<Target> begin();
+ template<class Target>
+ ManagedPtr<Target> begin();
- 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.
+ 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;
+ private:
+ std::vector<MetaRuleAbstract*> __rules;
+ std::vector<Function*> __functions;
+ std::vector<CodeScope*> __scopes;
- FUNCTIONS_REGISTRY __indexFunctions;
+ FUNCTIONS_REGISTRY __indexFunctions;
- // ***** TYPES SECTION *****
- public:
-std::map<std::string, TypeAnnotation> __indexTypeAliases;
-ExpandedType expandType(const TypeAnnotation &t) const;
-ExpandedType findType(const std::string& name);
-void add(TypeAnnotation&& t, Atom<Identifier_t>&& alias);
-void recognizeVariantIdentifier(Expression& identifier);
+ // ***** TYPES SECTION *****
+ public:
+ std::map<std::string, TypeAnnotation> __indexTypeAliases;
+ ExpandedType expandType(const TypeAnnotation &t) const;
+ ExpandedType findType(const std::string& name);
+ void add(TypeAnnotation t, Atom<Identifier_t> alias);
+ void recognizeVariantIdentifier(Expression& identifier);
- private:
-std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
-ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
- const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
+ private:
+ std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
+ ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
+ const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
- // ***** TYPES SECTION END *****
-};
+ // ***** TYPES SECTION END *****
+ };
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
}
#endif // AST_H
diff --git a/cpp/src/attachments.cpp b/cpp/src/attachments.cpp
index d8c8af3..83a54d1 100644
--- a/cpp/src/attachments.cpp
+++ b/cpp/src/attachments.cpp
@@ -1,23 +1,30 @@
//
// Created by pgess on 3/15/15.
//
#include "attachments.h"
-#include "ast.h"
-void xreate::SymbolAttachments::put(xreate::Symbol const &symbol, unsigned int key, void *data) {
- symbol.scope->attachments.__data[key].emplace(symbol.identifier, data);
-}
+namespace xreate {
+ void* xreate::Attachments::put(unsigned int key, void *data) {
+ auto result = __data.emplace(key, data);
+
+ void* ptrOld = nullptr;
+ if (!result.second){
+ ptrOld = result.first->second;
+ result.first->second = data;
+ }
+
+ return ptrOld;
+ }
-void *xreate::SymbolAttachments::get(xreate::Symbol const &symbol, unsigned int key, void *def) {
- if (symbol.scope->attachments.__data[key].count(symbol.identifier))
- return symbol.scope->attachments.__data[key].at(symbol.identifier);
+ void *xreate::Attachments::get(unsigned int key) {
+ assert(__data.count(key));
+ return __data.at(key);
+ }
- return def;
-}
-
-bool
-xreate::SymbolAttachments::exists(const Symbol& symbol, unsigned int key)
-{
- return symbol.scope->attachments.__data.count(key) && symbol.scope->attachments.__data.at(key).count(symbol.identifier);
-}
+ bool
+ xreate::Attachments::exists(unsigned int key)
+ {
+ return __data.count(key)>0;
+ }
+}
\ No newline at end of file
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index 08b8579..a62cd20 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,143 +1,124 @@
//
// Created by pgess on 3/15/15.
//
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <map>
#include <assert.h>
#include <type_traits>
namespace xreate
{
- //Attachemnt Tags:
- struct IsDeclVisited{};
- struct IsImplementationOnTheFly{};
-
- //Atachments dictionary
+ //Attachments dictionary
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
+ // static const unsigned int key (current unreserved - 5);
};
-
- template<>
- struct AttachmentsDict<IsDeclVisited>
- {
- typedef bool Data;
- static const unsigned int key = 0;
- };
-
- template<>
- struct AttachmentsDict<IsImplementationOnTheFly>
+
+ template<class T>
+ struct AttachmentsStorage
{
- typedef bool Data;
- static const unsigned int key = 3;
+ //static Attachments* get(const T&);
};
+ namespace detail {
+ template<class Typ>
+ typename std::enable_if<std::is_pointer<Typ>::value, void*>::type
+ __wrap(const Typ& value){
+ return value;
+ }
+
+ template<class Typ>
+ typename std::enable_if<std::is_pointer<Typ>::value, Typ>::type
+ __unwrap(void* value){
+ return reinterpret_cast<Typ>(value);
+ }
+
+ template<class Typ>
+ typename std::enable_if<! std::is_pointer<Typ>::value, void*>::type
+ __wrap(const Typ& value){
+ Typ* holder = new Typ(value);
+ return holder;
+ }
+
+ template<class Typ>
+ typename std::enable_if<! std::is_pointer<Typ>::value, Typ&>::type
+ __unwrap(void* value){
+ return *reinterpret_cast<Typ*>(value);
+ }
- class Symbol;
- typedef unsigned int VID;
-
- class AttachmentsImpl
- {
- friend class SymbolAttachments;
-
- };
-
- //TODO copy function to copy whole data from symbol to symbol: copy(sTo, sFrom);
- class SymbolAttachments
+ template<class Typ>
+ typename std::enable_if<std::is_pointer<Typ>::value, void>::type
+ __delete(void* value){
+ delete reinterpret_cast<Typ>(value);
+ }
+
+ template<class Typ>
+ typename std::enable_if<! std::is_pointer<Typ>::value, void>::type
+ __delete(void* value){
+ delete reinterpret_cast<Typ*>(value);
+ }
+ }
+
+ //TODO copy whole data from symbol to symbol: copy(sTo, sFrom);
+ class Attachments
{
public:
//TODO add specialization for pointers
template<class Tag>
using Data = typename AttachmentsDict<Tag>::Data;
- template<class Tag>
- using Input = typename std::conditional<std::is_pointer<Data<Tag>>::value, Data<Tag>, Data<Tag>&&>::type;
-
- template<class Tag>
- static typename std::enable_if<std::is_pointer<Data<Tag>>::value>::type
- put(const Symbol& symbol, Input<Tag> data)
+ template<class Holder, class Tag>
+ static void put(const Holder& holder, const Data<Tag>& data)
{
const unsigned int key = AttachmentsDict<Tag>::key;
- put(symbol, key, (void*) data);
- }
+ Attachments* self = AttachmentsStorage<Holder>::get(holder);
- template<class Tag>
- static typename std::enable_if<! std::is_pointer<Data<Tag>>::value>::type
- put(const Symbol& symbol, Input<Tag> data)
- {
- const unsigned int key = AttachmentsDict<Tag>::key;
- Data<Tag>* holder = new Data<Tag>(data);
- put(symbol, key, (void*) holder);
- }
-
- /*
- template<class Tag>
- using Tag2 = std::enable_if<std::is_pointer<Tag>, Tag>::
- static void put(const Symbol& symbol, typename AttachmentsDict<Tag>::Data && data)
- {
- typedef typename AttachmentsDict<Tag>::Data Typ;
- Typ* ptr = new Typ(data);
-
- AttachmentsImpl::put(symbol, ptr);
- }
- */
-
- template<class Tag>
- static typename AttachmentsDict<Tag>::Data& get(const Symbol& symbol, typename AttachmentsDict<Tag>::Data&& valueDefault)
- {
- typedef typename AttachmentsDict<Tag>::Data Typ;
- const unsigned int key = AttachmentsDict<Tag>::key;
-
- Typ* def = new Typ(valueDefault);
- Typ* result = static_cast<Typ*> (get(symbol, key, def));
-
- if (result != def) delete def; //TODO check is there some mem leaks?
- return *result;
+ void* dataWaste = self->put(key, detail::__wrap(data));
+ detail::__delete<Data<Tag>>(dataWaste);
}
- template<class Tag>
- static typename std::enable_if<std::is_pointer<Data<Tag>>::value, Data<Tag>>::type
- get(const Symbol& symbol)
+ template<class Holder, class Tag>
+ static Data<Tag>& get(const Holder& holder)
{
const unsigned int key = AttachmentsDict<Tag>::key;
- Data<Tag> result = reinterpret_cast<Data<Tag>> (get(symbol, key, nullptr));
+ Attachments* self = AttachmentsStorage<Holder>::get(holder);
- assert(result != nullptr); // data not found for the symbol
- return result;
+ return detail::__unwrap<Data<Tag>>(self->get(key));
}
-
- template<class Tag>
- static typename std::enable_if<! std::is_pointer<Data<Tag>>::value, Data<Tag>&>::type
- get(const Symbol& symbol)
+
+ template<class Holder, class Tag>
+ static Data<Tag> get(const Holder& holder, Data<Tag>&& dataDefault)
{
+ if (! exists<Holder, Tag>(holder)){
+ return dataDefault;
+ }
+
const unsigned int key = AttachmentsDict<Tag>::key;
+ Attachments* self = AttachmentsStorage<Holder>::get(holder);
- Data<Tag>* result = reinterpret_cast<Data<Tag>*> (get(symbol, key, nullptr));
-
- assert(result != nullptr); // data not found for the symbol
- return *result;
+ return detail::__unwrap<Data<Tag>>(self->get(key));
}
- template<class Tag>
- static bool exists(const Symbol& symbol)
+ template<class Holder, class Tag>
+ static bool exists(const Holder& holder)
{
const unsigned int key = AttachmentsDict<Tag>::key;
- return exists(symbol, key);
+ Attachments* self = AttachmentsStorage<Holder>::get(holder);
+ return self->exists(key);
}
private:
- typedef std::map<VID, void*> Attachment;
- std::map<unsigned int, Attachment> __data;
-
- static void put(const Symbol& symbol, unsigned int key, void* data);
- static void* get(const Symbol& symbol, unsigned int key, void *def);
- static bool exists(const Symbol& symbol, unsigned int key);
+ std::map<unsigned int, void*> __data;
+ void* put(unsigned int key, void *data);
+ void* get(unsigned int key);
+ bool exists(unsigned int key);
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index 21237f6..c1a6b7c 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,689 +1,274 @@
#include "clasplayer.h"
#include <iostream>
#include "utils.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <gringo/scripts.hh>
+#include "analysis/aux.h"
+#include "analysis/DominatorsTreeAnalysisProvider.h"
+#include "analysis/cfagraph.h"
+#include "analysis/dfagraph.h"
+
using namespace std;
//TODO escape identifiers started from upper case symbol
namespace xreate {
void
ClaspLayer::printWarnings(std::ostream& out)
{
const std::string warningTag = "warning";
auto warningsRange = __model.equal_range(warningTag);
for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) {
unsigned int warningId;
- Gringo::Value params;
- std::tie(warningId, params) = parse<unsigned int, Gringo::Value>(warning->second);
+ 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
- ClaspLayer::onModel(Gringo::Model const &model) {
+ ClaspLayer::handlerSolution(Gringo::Model const &model) {
std::list<std::string> warnings;
cout << "Model: " << endl;
const string& atomBindVar = Config::get("clasp.bindings.variable");
const string& atomBindFunc = Config::get("clasp.bindings.function");
const string& atomBindScope = Config::get("clasp.bindings.scope");
- for (Gringo::Value atom : model.atoms(Gringo::Model::ATOMS)) {
+ for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
atom.print(cout);
cout <<" | "<< endl;
- if (*atom.name() == atomBindVar || *atom.name() == atomBindFunc || *atom.name() == atomBindScope){
- string name = *std::get<1>(parse<Gringo::Value, Gringo::Value>(atom)).name();
+ string atomName(atom.name().c_str());
+ if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){
+ string name = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.emplace(move(name), move(atom));
}
- __model.emplace(*atom.name(), move(atom));
+ __model.emplace(atomName, move(atom));
}
return true;
}
- 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;
- }
-
void
- ClaspLayer::setCFAData(CFAGraph &&graph) {
- cfagraph = graph;
+ ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) {
+ dataCFA.reset(graph);
}
-
- void
- ClaspLayer::addDFAData(DFAGraph &&graph)
- {
- dfaData = graph;
- std::set<SymbolPacked> symbols;
- ostream &cout = __partGeneral;
-
- cout << endl << "%\t\tStatic analysis: DFA" << endl;
-
- std::vector<std::pair<SymbolPacked, SymbolPacked>>::iterator i1;
- std::vector<DFGConnection>::iterator i2;
-
- boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
- boost::format format2Args("(%1%, %2%)");
- for (i1= dfaData.__edges.begin(), i2 = dfaData.__data.begin(); i1!= dfaData.__edges.end(); ++i1, ++i2 )
- {
- string edgeName;
- switch (*i2)
- {
- case DFGConnection::OPT: edgeName = "opt"; break;
- case DFGConnection::ALIAS: edgeName = "alias"; break;
- case DFGConnection::PROTO: edgeName = "proto"; break;
- }
-
- cout << formatDfaConnection
- %(format2Args %(i1->first.identifier) %(i1->first.scope)).str()
- %(format2Args %(i1->second.identifier) %(i1->second.scope)).str()
- %edgeName
- << " %" <<getHintForPackedSymbol(i1->first) << " - " << getHintForPackedSymbol(i1->second)
- <<endl;
-
- symbols.insert(i1->first);
- symbols.insert(i1->second);
- }
-
- boost::format formatBind("bind(%1%, %2%).");
- for (const pair<SymbolPacked, Expression>& tag: dfaData.__tags)
- {
- for (string variant: compile(tag.second)) {
- cout << (formatBind
- % (format2Args %(tag.first.identifier) %(tag.first.scope))
- % (variant))
- << "%" << getHintForPackedSymbol(tag.first)
- << endl;
- }
-
- symbols.insert(tag.first);
- }
-
- for (const SymbolPacked& s: symbols)
- {
- cout << "v(" << format2Args % (s.identifier) % (s.scope) << ")."
- << " %" << getHintForPackedSymbol(s)
- <<endl;
- }
+
+ void
+ ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){
+ dataDFA.reset(graph);
}
-
- void
- ClaspLayer::involveCFAData() {
- ostream &cout = __partTags;
- const std::string& atomBinding = Config::get("clasp.bindings.function");
- const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
-
- //show function tags
- int counterTags = 0;
- std::ostringstream bufFunctionNames;
- boost::format formatFunction("function(%1%).");
- boost::format formatBind(atomBinding + "(%1%, %2%).");
- for (auto function: cfagraph.__nodesFunction.left) {
- const auto tags = cfagraph.__functionTags.equal_range(function.first);
- if (tags.first == tags.second) {
- //no tags
- bufFunctionNames << "; " << function.second ;
- continue;
- }
-
- cout << formatFunction % (function.second) << std::endl;
- for (const auto& tag_: boost::make_iterator_range(tags)){
- const Tag& tag = tag_.second;
-
- list<string> tagRaw = compile(tag.first);
- assert(tagRaw.size() == 1);
-
- cout << formatBind
- % (function.second)
- % (tagRaw.front())
- << endl;
- ++counterTags;
- }
- }
-
- if (bufFunctionNames.tellp()){
- cout << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
- }
-
- if (counterTags == 0) {
- cout << "%no functtion tags at all" << endl;
- }
-
- //declare scopes
- boost::format formatScope("scope(0..%1%).");
- cout << formatScope % (__registryScopes.size() - 1) << std::endl;
-
- //show context rules:
- for (auto rule: cfagraph.__contextRules) {
- cout << ContextRule(rule.second).compile(rule.first) << std::endl;
- };
-
- //show scope tags:
- counterTags = 0;
- boost::format formatScopeBind(atomBindingScope + "(%1%, %2%).");
- for (auto entry: cfagraph.__scopeTags) {
- ScopePacked scopeId = entry.first;
- const Expression& tag = entry.second;
- list<string> tagRaw = compile(tag);
- assert(tagRaw.size() == 1);
-
- cout << formatScopeBind % scopeId %(tagRaw.front()) << endl;
- ++counterTags;
- }
-
- if (counterTags == 0) {
- cout << "%scope tags: no tags at all" << endl;
- }
-
- cout << endl << "%\t\tStatic analysis: CFA" << endl;
-
- //parent connections
- //TEST CFG parent function
- boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
- for (const auto &relation: cfagraph.__parentFunctionRelations) {
- const string& function = cfagraph.__nodesFunction.left.at(relation.second);
-
- cout << formatFunctionParent % relation.first % function << endl;
- }
-
- //TEST CFG parent scope
- boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
- for (const auto &relation: cfagraph.__parentScopeRelations) {
- cout << formatScopeParent % relation.first % relation.second << endl;
- }
-
- //call connections
- boost::format formatCall("cfa_call(%1%, %2%).");
-
- for (const auto &relation: cfagraph.__callRelations) {
- const ScopePacked scopeFrom = relation.first;
- const string& functionTo = cfagraph.__nodesFunction.left.at(relation.second);
-
- cout << formatCall % (scopeFrom) % (functionTo) << endl;
- }
-
- //function specializations descrtiption
- //SECTIONTAG late-context cfa_function_specializations
- boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
- const list<ManagedFnPtr>& functions = ast->getAllFunctions();
- for (auto f: functions){
- if (f->guardContext.isValid()){
- list<string> guardRaw = compile(f->guardContext);
- assert(guardRaw.size() == 1);
- cout << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
- }
- }
- }
-
+
void
ClaspLayer::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 compile(guard);
+ return xreate::analysis::compile(guard);
});
- const list<string>& guards = multiplyLists(std::move(guardsRaw));
- list<string> &&branches = compileNeg(rule.__condition);
+ 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;
}
}
- std::list<std::string>
- ClaspLayer::compile(const Expression &e){
- list<string> result;
-
- switch (e.op) {
- case Operator::CALL: {
- assert(e.__state == Expression::COMPOUND);
-
- std::list<list<string>> operands;
- std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
- [](const Expression &e) {
- return ClaspLayer::compile(e);
- });
-
- list<string> &&operands_ = multiplyLists(std::move(operands));
- result.push_back(boost::str(boost::format("%1%(%2%)") % (e.__valueS) % (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::NONE: {
- switch (e.__state) {
- case Expression::IDENT:
- result.push_back(e.__valueS);
- break;
-
- case Expression::NUMBER:
- result.push_back(to_string(e.__valueD));
- break;
-
- default:
- assert(true);
- }
- break;
- }
-
- default: break;
- }
-
-//TODO Null ad hoc ClaspLayer implementation
-// if (e.isNone()){
-// result.push_back(e.__valueS);
-// }
-
- assert(result.size());
- return result;
- }
-
- std::list<std::string>
- ClaspLayer::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;
- }
+
unsigned int
ClaspLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
ClaspLayer::involveImports() {
ostream &out = __partGeneral;
for (string fn: ast->__rawImports)
{
std::ifstream file(fn);
if (!file) continue;
while(!file.eof()){
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
- ClaspLayer::addRawScript(std::string&& script){
+ ClaspLayer::addRawScript(std::string&& script){
__partGeneral << script;
}
void
ClaspLayer::run() {
involveImports();
- involveCFAData();
+ this->dataDFA->print(__partGeneral);
+ this->dataCFA->print(__partGeneral);
+
+ DominatorsTreeAnalysisProvider providerDominators;
+ providerDominators.run(this);
+ providerDominators.print(__partGeneral);
+
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
- ClingoLib ctl(scriptsDefault, 0, args.data());
+ 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->onModel(model);
+ this->handlerSolution(model);
return true;
}, {});
- if (result == Gringo::SolveResult::SAT) {
+ if (result.satisfiable() == Gringo::SolveResult::Satisfiable) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process clasp data
for (auto q: __queries)
{
q.second->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
ClaspLayer::ModelFragment
ClaspLayer::query(const std::string& atom)
{
if (! __model.count(atom)){
return boost::none;
}
return ModelFragment(__model.equal_range(atom));
}
ScopePacked
- ClaspLayer::pack(CodeScope* const scope) {
+ ClaspLayer::pack(CodeScope* const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
+
+ size_t
+ ClaspLayer::getScopesCount() const{
+ return __registryScopes.size();
+ }
SymbolPacked
- ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
+ ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
SymbolPacked result;
result.scope = pack(symbol.scope);
result.identifier = symbol.identifier;
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
-
+
Symbol
- ClaspLayer::unpack(const SymbolPacked& symbol)
+ ClaspLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
};
std::string
- ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
- auto result = __indexSymbolNameHints.find(symbol);
- return (result == __indexSymbolNameHints.end())? "" : result->second;
- }
-
-/*
-void AspOutPrinter::reportSolution(const Clasp::Solver&, const Clasp::Enumerator&, bool complete) {
- if (complete) std::cout << "No more models!" << std::endl;
- else std::cout << "More models possible!" << std::endl;
-}
-
-
-void AspOutPrinter::reportModel(const Clasp::Solver& s, const Clasp::Enumerator&) {
- std::cout << "Model " << s.stats.solve.models << ": \n";
-// get the symbol table from the solver
- const Clasp::AtomIndex& symTab = *s.strategies().symTab;
- for (Clasp::AtomIndex::const_iterator it = symTab.begin(); it != symTab.end(); ++it)
- {
-// print each named atom that is true w.r.t the current assignment
- }
- std::cout << std::endl;
-}
-
-*/
-/*****************************************
- * CFAGraph
- *****************************************
- */
- void
- CFAGraph::addFunctionAnnotations(const std::string& function, const std::vector<Tag>&tags) {
- unsigned int fid = registerNodeFunction(function);
-
- for (Tag tag: tags){
- __functionTags.emplace(fid, tag);
- }
- }
-
- 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& scopeFrom, const std::string& functionTo) {
- unsigned int idFuncTo = registerNodeFunction(functionTo);
-
- __callRelations.emplace(scopeFrom, idFuncTo);
- }
-
- void
- CFAGraph::addParentConnection(const ScopePacked& scope, const std::string& functionParent){
- __parentFunctionRelations.emplace(scope, registerNodeFunction(functionParent));
- }
-
- void
- CFAGraph::addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent){
- __parentScopeRelations.emplace(scope, scopeParent);
- }
-
- unsigned int
- CFAGraph::registerNodeFunction(const std::string& fname){
- auto pos = __nodesFunction.left.insert(make_pair(__nodesFunction.size(), fname));
-
- return pos.first->first;
- }
-
-
-
-/*****************************************
- * DFAGraph
- *****************************************
- */
-
- class VisitorAddTag: public boost::static_visitor<> {
- public:
- void operator()(const SymbolPacked& symbol){
- __graph->__tags.emplace(symbol, move(__tag));
- }
-
- void operator()(SymbolTransient& symbol){
- symbol.tags.push_back(move(__tag));
- }
-
- void operator()(const SymbolInvalid& symbol){
- assert(false && "Undefined behaviour");
- }
-
- VisitorAddTag(DFAGraph* const dfagraph, Expression&& tag):
- __graph(dfagraph), __tag(tag) {}
-
- private:
- DFAGraph* const __graph;
- Expression __tag;
- };
-
- class VisitorAddLink: public boost::static_visitor<> {
- public:
- void operator()(const SymbolPacked& nodeFrom){
- if (!__graph->isConnected(__nodeTo, nodeFrom))
- {
- __graph->__edges.emplace_back(__nodeTo, nodeFrom);
- __graph->__data.push_back(__link);
-
- DFAGraph::EdgeId eid = __graph->__edges.size()-1;
- __graph->__outEdges.emplace(nodeFrom, eid);
- }
- }
-
- void operator()(const SymbolTransient& symbolFrom){
- if (__link != DFGConnection::ALIAS){
- assert(false && "Undefined behaviour");
- }
-
- for (const Expression& tag: symbolFrom.tags){
- __graph->__tags.emplace(__nodeTo, tag);
- }
- }
-
- void operator()(const SymbolInvalid&){
- if (__link == DFGConnection::ALIAS) return;
- if (__link == DFGConnection::OPT) return;
-
- assert(false && "Undefined behaviour");
- }
-
- VisitorAddLink(DFAGraph* const dfagraph, const SymbolPacked& nodeTo, DFGConnection link):
- __graph(dfagraph), __nodeTo(nodeTo), __link(link) {}
-
- private:
- DFAGraph* const __graph;
- SymbolPacked __nodeTo;
- DFGConnection __link;
- };
-
- bool
- DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom)
- {
- auto range = __outEdges.equal_range(identifierFrom);
-
- for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
- {
- if (__edges[edge->second].second == identifierTo)
- return true;
+ ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
+ if (!symbol.categoryTransient) {
+ auto result = __indexSymbolNameHints.find(symbol);
+ return (result == __indexSymbolNameHints.end())? "" : result->second;
+
+ } else {
+ return "anonym(" + to_string(symbol.identifier) + ")";
}
-
- return false;
}
-
- void
- DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
- VisitorAddLink visitor(this, nodeTo, link);
- boost::apply_visitor(visitor, nodeFrom);
- }
-
- void
- DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) {
- VisitorAddTag visitor(this, move(tag));
- boost::apply_visitor(visitor, node);
- }
-
+
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
IQuery*
- ClaspLayer::registerQuery(IQuery *query, const QueryId& id) {
+ ClaspLayer::registerQuery(IQuery *query, const QueryId& id) {
return __queries.emplace(id, query).first->second;
}
IQuery*
- ClaspLayer::getQuery(const QueryId& id){
+ ClaspLayer::getQuery(const QueryId& id){
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
}
+
diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h
index f920106..76d83f3 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,239 +1,227 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_H
#include "ast.h"
#include "contextrule.h"
#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <boost/bimap.hpp>
+#include <boost/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
+#include <boost/scoped_ptr.hpp>
#include <list>
namespace xreate {
- typedef unsigned int ScopePacked;
+ typedef unsigned int ScopePacked;
- class CFAGraph {
- friend class ClaspLayer;
-
- public:
- void addFunctionAnnotations(const std::string& function, const std::vector<Tag>&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& scopeFrom, const std::string& functionTo);
- void addParentConnection(const ScopePacked& scope, const std::string& functionParent);
- void addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent);
-// void addScopeRetIdentifier(const ScopePacked& scope, const SymbolPacked& identifier);
-
- private:
- std::map<ScopePacked, unsigned int> __parentFunctionRelations;
- std::map<ScopePacked, ScopePacked> __parentScopeRelations;
- std::set<std::pair<ScopePacked, unsigned int>> __callRelations;
- boost::bimap<unsigned int, std::string > __nodesFunction;
- std::multimap<unsigned int, Tag> __functionTags;
- std::multimap<ScopePacked, Expression> __scopeTags;
- std::multimap<ScopePacked, ContextRule> __contextRules;
-
- unsigned int registerNodeFunction(const std::string& fname);
- };
-
-
-
- struct SymbolPacked
- {
+ struct SymbolPacked {
VID identifier;
ScopePacked scope;
+ bool categoryTransient = false;
};
- struct SymbolTransient{
- std::list<Expression> tags;
- };
-
- struct SymbolInvalid{};
-
- typedef boost::variant<SymbolPacked, SymbolTransient, SymbolInvalid> SymbolNode;
-
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
- enum class DFGConnection{
- ALIAS, OPT, PROTO};
-
- class VisitorAddTag;
- class VisitorAddLink;
+ enum class DFGConnection {
+ STRONG, WEAK, PROTOTYPE
+ };
- class DFAGraph
- {
- friend class ClaspLayer;
- friend class VisitorAddTag;
- friend class VisitorAddLink;
+ class IAnalysisData {
public:
- void addAnnotation(SymbolNode& identifier, Expression&& tag);
- void addConnection(const SymbolPacked& identifierTo, const SymbolNode& identifierFrom, DFGConnection link);
- bool isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom);
-
- private:
- typedef unsigned int EdgeId;
- std::vector<std::pair<SymbolPacked, SymbolPacked>> __edges;
- std::multimap<SymbolPacked, EdgeId> __outEdges;
- std::vector<DFGConnection> __data;
- std::multimap<SymbolPacked, Expression> __tags;
+ void print(std::ostringstream& output) const;
+ virtual ~IAnalysisData(){};
};
-
- class IQuery {
+
+ class IQuery {
public:
- virtual void init(ClaspLayer* clasp)=0;
+ virtual void init(ClaspLayer* clasp) = 0;
virtual ~IQuery() {}
};
- enum class QueryId{
- ContainersQuery,
- ContextQuery,
- PtrvalidQuery
+ enum class QueryId {
+ ContainersQuery,
+ ContextQuery,
+ PtrvalidQuery
};
+ namespace analysis{
+ class DFAGraph;
+ class CFAGraph;
+ }
+
class ClaspLayer {
- friend class ContextRule;
+ friend class ContextRule;
+ //PROVIDERS:
public:
- AST *ast;
- DFAGraph dfaData;
- CFAGraph cfagraph;
+ boost::scoped_ptr<xreate::analysis::DFAGraph> dataDFA;
+ void setDFAData(xreate::analysis::DFAGraph* graph);
- ClaspLayer();
+ boost::scoped_ptr<xreate::analysis::CFAGraph> dataCFA;
+ void setCFAData(xreate::analysis::CFAGraph* graph);
+
+ void addRawScript(std::string&& script);
+
+ private:
+ void involveImports();
+
+ //QUERIES
+ public:
IQuery* registerQuery(IQuery* query, const QueryId& id);
IQuery* getQuery(const QueryId& id);
- void addFunctionTags(const std::string &function, const std::vector<Tag> &tags);
- void setCFAData(CFAGraph &&graph);
- void addDFAData(DFAGraph &&graph);
- void addRuleWarning(const RuleWarning &rule);
-
- void run();
template<class ...Types>
- static std::tuple<Types...> parse(const Gringo::Value& atom);
+ static std::tuple<Types...> parse(const Gringo::Symbol& atom);
- typedef std::multimap<std::string, Gringo::Value>::const_iterator ModelIterator;
- typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelFragment;
+ typedef std::multimap<std::string, Gringo::Symbol>::const_iterator ModelIterator;
+ typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelFragment;
ModelFragment query(const std::string& atom);
- ScopePacked pack(CodeScope* const scope);
- SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
+ size_t getScopesCount() const;
+ SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
+ ScopePacked pack(CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol);
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
- void addRawScript(std::string&& script);
private:
- // all query plugins to process clasp data
std::map<QueryId, IQuery*> __queries;
- std::multimap<std::string, Gringo::Value> __model;
- std::map<unsigned int, std::string> __warnings;
- std::ostringstream __partTags;
- std::ostringstream __partGeneral;
+ std::multimap<std::string, Gringo::Symbol> __model;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
-
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<CodeScope*> __registryScopes;
- void printWarnings(std::ostream& out);
- bool onModel(Gringo::Model const &model);
- static std::list<std::string> compile(const Expression &e);
- static std::list<std::string> compileNeg(const Expression &e);
+ //WARNINGS
+ //TODO move to separate provider/query
+ public:
+ void addRuleWarning(const RuleWarning &rule);
unsigned int registerWarning(std::string &&message);
- void involveImports();
- void involveCFAData();
+
+ private:
+ std::map<unsigned int, std::string> __warnings;
+ void printWarnings(std::ostream& out);
+
+ //DEFAULT
+ public:
+ AST *ast;
+
+ ClaspLayer();
+ void run();
+
+ private:
+ std::ostringstream __partTags;
+ std::ostringstream __partGeneral;
+
+ bool handlerSolution(Gringo::Model const &model);
};
template<class typ>
struct ParseImplAtom {
- static typ get(const Gringo::Value& atom)
- {
+
+ static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<std::string> {
- static std::string get(const Gringo::Value& atom)
- {
- return *atom.string();
- }};
+ static 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");
+ }
+ };
template<>
struct ParseImplAtom<SymbolPacked> {
- static SymbolPacked get(const Gringo::Value& atom)
- {
+
+ static SymbolPacked get(const Gringo::Symbol& atom) {
auto result = ClaspLayer::parse<unsigned int, unsigned int>(atom);
return SymbolPacked{std::get<0>(result), std::get<1>(result)};
- }};
+ }
+ };
template<>
- struct ParseImplAtom<Gringo::Value> {
- static Gringo::Value get(const Gringo::Value& atom)
- {
+ struct ParseImplAtom<Gringo::Symbol> {
+
+ static Gringo::Symbol get(const Gringo::Symbol& atom) {
return atom;
- }};
+ }
+ };
template<>
struct ParseImplAtom<Expression> {
- static Expression get(const Gringo::Value& atom)
- {
- switch (atom.type()){
- case Gringo::Value::NUM: return Expression(atom.num());
- case Gringo::Value::ID: return Expression((std::string(atom.string())));
- case Gringo::Value::FUNC: {
- Expression result(Operator::CALL, {Expression(std::string(atom.name()))});
- for(const Gringo::Value& arg: atom.args()){
- result.addArg(ParseImplAtom<Expression>::get(arg));
- }
-
- return result;
- }
-
- default: {
- assert(false);
- }
- }
- }};
+
+ static Expression get(const Gringo::Symbol& atom) {
+ switch (atom.type()) {
+ case Gringo::SymbolType::Num: return Expression(atom.num());
+ case Gringo::SymbolType::Str: return Expression(std::string(atom.string().c_str()));
+
+ case Gringo::SymbolType::Fun:
+ {
+ //ID
+ if (!atom.args().size){
+ return Expression(std::string(atom.name().c_str()));
+ }
+
+ //FUNC
+ Expression result(Operator::CALL,{Expression(std::string(atom.name().c_str()))});
+ for (const Gringo::Symbol& arg : atom.args()) {
+ result.addArg(ParseImplAtom<Expression>::get(arg));
+ }
+
+ return result;
+ }
+
+ default:
+ {
+ assert(false);
+ }
+ }
+ }
+ };
template<class Tuple, size_t index>
struct Parse_Impl {
- static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
- {
+
+ 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;
+ typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType;
- ElType& el = std::get<tupleSize - index>(tup);
+ ElType& el = std::get < tupleSize - index > (tup);
- Gringo::Value atom = *arg;
+ Gringo::Symbol atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
- Parse_Impl<Tuple, index-1>::parse(tup, ++arg);
+ Parse_Impl<Tuple, index - 1 > ::parse(tup, ++arg);
}
};
template<class Tuple>
- struct Parse_Impl<Tuple, 0>
- {
- static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
- {}
- };
+ struct Parse_Impl<Tuple, 0> {
+ static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
+ }
+ };
template<class ...Types>
std::tuple<Types...>
- ClaspLayer::parse(const Gringo::Value& atom)
- {
- typedef std::tuple<Types...> Tuple;
+ ClaspLayer::parse(const Gringo::Symbol& atom) {
+ typedef std::tuple < Types...> Tuple;
Tuple tup;
- Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().begin());
+ Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
}
#endif
diff --git a/cpp/src/compilation/instr-containers.cpp b/cpp/src/compilation/advanced.cpp
similarity index 57%
rename from cpp/src/compilation/instr-containers.cpp
rename to cpp/src/compilation/advanced.cpp
index 2cbf0a0..db651c0 100644
--- a/cpp/src/compilation/instr-containers.cpp
+++ b/cpp/src/compilation/advanced.cpp
@@ -1,575 +1,449 @@
-#include "instr-containers.h"
-#include "llvmlayer.h"
-#include "ast.h"
+/*
+ * File: InstructionsAdvanced.cpp
+ * Author: pgess
+ *
+ * Created on June 26, 2016, 6:00 PM
+ */
+
+#include <compilation/transformations.h>
+#include "compilation/advanced.h"
+#include "compilation/containers.h"
+
#include "query/context.h"
#include "query/containers.h"
#include "query/ptrvalid.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::CodeScopeUnit* scope = context.scope; \
compilation::FunctionUnit* function = context.function;
-Instructions::Instructions(compilation::Context ctx)
+Advanced::Advanced(compilation::Context ctx)
: context(ctx), tyNum (static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num)))))
{}
llvm::Value*
-Instructions::compileMapSolid(const Expression &expr, const std::string hintRetVar) {
+Advanced::compileMapSolid(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT
//initialization
std::string varIn = expr.getOperands()[0].getValueString();
Symbol symbolIn = scope->scope->findSymbol(varIn);
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->__args[0];
+ 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::getGlobalContext(), "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "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::CodeScopeUnit* 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, blockLoop);
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
-Instructions::compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string hintRetVar)
+Advanced::compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string hintRetVar)
{
EXPAND_CONTEXT
UNUSED(function);
//TODO find out symbol identifier in order to name it in raw llvm;
llvm::Value* data = scope->compileSymbol(dataSymbol);
const Expression& decl = CodeScope::findDeclaration(dataSymbol);
+ //TODO review array index compilation strategy
if (decl.op == Operator::LIST) {
assert(indexes.size() == 1);
return llvm->builder.CreateExtractElement(data, indexes[0], NAME("el"));
}
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
Value *pEl = llvm->builder.CreateGEP(data, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
-Instructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx){
+Advanced::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx){
EXPAND_CONTEXT
UNUSED(scope);
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){
std::vector<llvm::Value*> refs;
llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::ConstantInt* zero = llvm::ConstantInt::get(tyInt, 0, false);
llvm::BasicBlock *blockSafe = llvm::BasicBlock::Create(llvm::getGlobalContext(), "safe", function->raw);
- // safety check: not null ptr
- Symbol s;
- if (! QueryPtrValid::assertValidPtr(s)){
- PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
- llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
- Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
+ // TODO review safety check: not null ptr
+ // SECTIONTAG validptr exception
+ Symbol s;
+ if (! QueryPtrValid::assertValidPtr(s)){
+ PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
+ llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
+ Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
- llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
- llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
- llvm->initExceptionBlock(blockException);
- }
+ llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
+ llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
+ llvm->initExceptionBlock(blockException);
+ }
- llvm->builder.SetInsertPoint(blockSafe);
+ llvm->builder.SetInsertPoint(blockSafe);
std::vector<Value*> indexes;
//dereference pointer
if (types.isPointer(t)){
indexes.push_back(zero);
}
- indexes.push_back(ConstantInt::get(tyInt, i));
-
- Value* addr = llvm->builder.CreateGEP(aggregate, indexes);
- return llvm->builder.CreateLoad(addr);
+ indexes.push_back(ConstantInt::get(tyInt, i));
- }
+ Value* addr = llvm->builder.CreateGEP(aggregate, indexes);
+ return llvm->builder.CreateLoad(addr);
+ }
}
assert(false && "not found required struct field");
+ return nullptr;
}
llvm::Value*
-Instructions::compileFold(const Expression& fold, const std::string& hintRetVar)
+Advanced::compileFold(const Expression& fold, const std::string& hintRetVar)
{
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = scope->scope->findSymbol(fold.getOperands()[0].getValueString());
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
- llvm::Value* rangeFrom = it->begin();
- llvm::Value* rangeTo = it->end();
+ 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::Value* valSat = nullptr;
- bool flagHasSaturation = false; //false; // TODO add `saturation` ann.
+ TransformerSaturation* transformerSaturation = context.pass->transformations->get<TransformerSaturation>();
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
+ llvm::BasicBlock *blockBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "body", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
- llvm::BasicBlock *blockEarly = llvm::BasicBlock::Create(llvm::getGlobalContext(), "earlyret", function->raw);
-
-
- // * initial check
- Value* condBefore = llvm->builder.CreateICmpNE(rangeFrom, rangeTo);
- llvm->builder.CreateCondBr(condBefore, blockLoop, blockEarly);
- llvm->builder.SetInsertPoint(blockEarly);
- llvm->builder.CreateRet(accumInit);
-
- //TODO implement saturation; add unittests;
- // Saturation check
- if (flagHasSaturation)
- {
- Value* condSat = llvm->builder.CreateICmpNE(accumInit, valSat);
- llvm->builder.CreateCondBr(condSat, blockLoop, blockAfterLoop);
- }
+ llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
- llvm::PHINode *accum = llvm->builder.CreatePHI(tyNum, 2, NAME("accum"));
+ llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
- llvm::PHINode *stateLoop = llvm->builder.CreatePHI(rangeFrom->getType(), 2, "foldIt");
- stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
+ llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
+ itLoop->addIncoming(rangeBegin, blockBeforeLoop);
// * loop body
+ llvm->builder.SetInsertPoint(blockBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
- Value* elIn = it->get(stateLoop);
+ Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
+ // * computing next iteration state
+ Value *itLoopNext = it->advance(itLoop);
+ accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
+ itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
+ llvm->builder.CreateBr(blockLoop);
+
// * break checks, continue checks
- if (flagHasSaturation)
+ //!! only after compiled Loop Body in order to fetch saturation expression
+ llvm->builder.SetInsertPoint(blockLoop);
+ if (transformerSaturation->exists())
{
- llvm::BasicBlock *blockChecks = llvm::BasicBlock::Create(llvm::getGlobalContext(), "checks", function->raw);
- Value* condSat = llvm->builder.CreateICmpNE(accumNext, valSat);
- llvm->builder.CreateCondBr(condSat, blockChecks, blockAfterLoop);
- llvm->builder.SetInsertPoint(blockChecks);
+ transformerSaturation->inject(blockBeforeLoop, blockAfterLoop, context);
}
- // * computing next iteration state
- Value *stateLoopNext = it->move(stateLoop);
- accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
- stateLoop->addIncoming(stateLoopNext, llvm->builder.GetInsertBlock());
- // * next iteration checks
- Value* condAfter = llvm->builder.CreateICmpNE(stateLoopNext, rangeTo);
- llvm->builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
+ // * next iteration checks
+ Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
+ llvm->builder.CreateCondBr(condRange, blockBody, blockAfterLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
llvm::Value*
-Instructions::compileLoopContext(const Expression& expression, const std::string& hintRetVar){
+Advanced:: compileFoldInf(const Expression& fold, const std::string& hintRetVar){
+ EXPAND_CONTEXT
+ assert(fold.op == Operator::FOLD_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::getGlobalContext(), "fold", function->raw);
+ llvm::BasicBlock *blockBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "body", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
+ TransformerSaturation* transformerSaturation = context.pass->transformations->get<TransformerSaturation>();
+
+ llvm->builder.CreateBr(blockLoop);
+
+ // * create phi
+ llvm->builder.SetInsertPoint(blockLoop);
+ llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
+ accum->addIncoming(accumInit, blockBeforeLoop);
+
+ // * loop body
+ llvm->builder.SetInsertPoint(blockBody);
+ CodeScope* scopeLoop = fold.blocks.front();
+ compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
+ unitLoop->bindArg(accum, move(accumName));
+ Value* accumNext = unitLoop->compile();
+
+ // * computing next iteration state
+ accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
+ llvm->builder.CreateBr(blockLoop);
+
+ // * break checks, continue checks
+ assert(transformerSaturation->exists());
+ llvm->builder.SetInsertPoint(blockLoop);
+ transformerSaturation->inject(blockBeforeLoop, blockAfterLoop, context);
+ llvm->builder.CreateBr(blockBody);
+
+ // finalization:
+ llvm->builder.SetInsertPoint(blockAfterLoop);
+ return accum;
+}
+
+llvm::Value*
+Advanced::compileLoopContext(const Expression& expression, const std::string& hintRetVar){
EXPAND_CONTEXT
llvm::IRBuilder<>& builder = llvm->builder;
ContextQuery* queryContext = reinterpret_cast<ContextQuery*> (context.pass->man->clasp->getQuery(QueryId::ContextQuery));
ScopePacked scopeOuterId = context.pass->man->clasp->pack(scope->scope);
- const ContextDomain& contextScopeOuter = queryContext->getContext(scopeOuterId);
+ const Domain& contextScopeOuter = queryContext->getContext(scopeOuterId);
std::string classSelected = expression.operands[0].getValueString();
std::list<Expression> elementsSelected;
for (const Expression& c: contextScopeOuter){
if (c.op == Operator::CALL && c.getValueString() == classSelected){
assert(c.operands.size());
elementsSelected.push_back(c.operands[0]);
}
}
assert(expression.blocks.size());
CodeScope* scopeInner = expression.blocks.front();
compilation::CodeScopeUnit* scopeInnerUnit = function->getScopeUnit(scopeInner);
ScopePacked scopeInnerId = context.pass->man->clasp->pack(scopeInner);
llvm::Value* result = nullptr;
for (const Expression& element: elementsSelected){
std::string blockName = "context" + element.getValueString();
llvm::BasicBlock *blockInner = llvm::BasicBlock::Create(llvm::getGlobalContext(), blockName, function->raw);
builder.CreateBr(blockInner);
builder.SetInsertPoint(blockInner);
queryContext->forceContext(scopeInnerId, {element});
scopeInnerUnit->reset();
result = scopeInnerUnit->compile();
}
return result;
}
llvm::Value*
-Instructions::compileIf(const Expression& exprIf, const std::string& hintRetVar)
+Advanced::compileIf(const Expression& exprIf, const std::string& hintRetVar)
{
EXPAND_CONTEXT
//initialization:
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
llvm::Type* tyResultType = llvm->toLLVMType(llvm->ast->expandType(exprIf.type));
llvm::BasicBlock *blockAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", function->raw);
llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", function->raw);
llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
llvm::PHINode *ret = builder.CreatePHI(tyResultType, 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
-
+//TODO Switch: default variant no needed when all possible conditions are considered
llvm::Value*
-Instructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar){
+Advanced::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar){
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
assert(exprSwitch.operands.size() >= 2);
assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT);
int countCases = exprSwitch.operands.size()-1;
llvm::IRBuilder<>& builder = llvm->builder;
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(ExpandedType(exprSwitch.type));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", function->raw);
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(conditionSwitch, blockDefault, countCases);
for (int size = exprSwitch.operands.size(), i=2; i<size; ++i){
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "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>(condCase), 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*
-Instructions::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
+Advanced::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
const size_t& __size = expr.getOperands().size();
const Expression& __data = expr;
ArrayType* typList = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I32, __size))));
Type*typI32 = llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::I32)));
std::vector<Constant *> list;
list.reserve(__size);
const std::vector<Expression> operands = __data.getOperands();
std::transform(operands.begin(), operands.end(), std::inserter(list, list.begin()),
[typI32](const Expression& e){return ConstantInt::get(typI32, e.getValueDouble());});
Value* listSource = ConstantArray::get(typList, ArrayRef<Constant*>(list));
/*
Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
*/
return listSource;
}
llvm::Value*
-Instructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar)
+Advanced::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar)
{
EXPAND_CONTEXT
UNUSED(function);
UNUSED(scope);
Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm::getGlobalContext()));
//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::getGlobalContext(), data);
Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 1, false));
llvm->builder.CreateStore(rawData, rawPtrData);
return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
}
-
-
-
-template<ImplementationType I>
-class IteratorForward;
-
-template<>
-class IteratorForward<ON_THE_FLY> : public Iterator {
-private:
- LLVMLayer* llvm;
- const xreate::Symbol current;
- const Symbol source;
- const ImplementationLinkedList linkedlist;
- CodeScope* const sourceScope;
- //TODO initialize ans mark as const (three fields)
- compilation::CodeScopeUnit* sourceUnit;
- compilation::FunctionUnit* function; //TODO is used somewhere?
- const Expression& sourceDecl;
- compilation::Context context;
- llvm::Type* sourceRawType =nullptr;
-
-public:
- IteratorForward(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(new compilation::CodeScopeUnit(source.scope, ctx.function, ctx.pass)),
- sourceDecl(CodeScope::findDeclaration(source)),
- context(ctx)
- {
- }
-
- llvm::Value* begin() {
- switch(sourceDecl.op) {
- case xreate::Operator::LIST:
- {
- sourceRawType = Type::getInt32Ty(llvm::getGlobalContext());
- return ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 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* 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);
- return sourceUnit->process(sourceDecl.operands.at(1));
- };
-
- default: break;
- }
-
- //return null pointer
- if (linkedlist){
- return ConstantPointerNull::getNullValue(sourceRawType);
- }
-
- assert(false && "Unknown declaration");
- return nullptr;
- }
-
- llvm::Value* get(Value* index,const std::string& hintRetVar="") override{
- const Expression& currentDecl = CodeScope::findDeclaration(current);
-
- switch (currentDecl.op) {
- case xreate::Operator::LIST: {
- //TODO re check is it right scope(source) to compilation currentDecl. Write unittests for this.
- //llvm::Value* currentValue = sourceUnit->process(currentDecl);
- return Instructions(context).compileArrayIndex(current, 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();
- const std::string& varIn = currentDecl.getOperands()[0].getValueString();
- std::string varEl = currentDecl.bindings[0];
-
- const Symbol& symbIn = current.scope->findSymbol(varIn);
- auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
-
- Value* elIn = it->get(index, varEl);
- compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
- unitLoop->bindArg(elIn, std::move(varEl));
- return unitLoop->compile();
- }
-
- case xreate::Operator::NONE: {
- assert(currentDecl.__state==Expression::IDENT);
- const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
- 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* move(Value* index, const std::string& hintRetVar) override{
- switch(sourceDecl.op)
- {
- case xreate::Operator::LIST:
- case xreate::Operator::LIST_RANGE:
- return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
-
- default: break;
- }
-
- if (linkedlist){
- ExpandedType tySource = llvm->ast->expandType(sourceScope->findDefinition(source));
- assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
- assert(tySource->__operands.size());
-
- return Instructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
- }
-
- assert(false && "Unknown declaration");
- return nullptr;
- }
-};
-
-Iterator*
-Iterator::create(compilation::Context context, const 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>());
-
- default: assert(true);
- }
-
- assert(false && "Unknown declaration");
- return nullptr;
-}
diff --git a/cpp/src/compilation/advanced.h b/cpp/src/compilation/advanced.h
new file mode 100644
index 0000000..c829320
--- /dev/null
+++ b/cpp/src/compilation/advanced.h
@@ -0,0 +1,47 @@
+/*
+ * File: InstructionsAdvanced.h
+ * Author: pgess
+ *
+ * Created on June 26, 2016, 6:00 PM
+ */
+
+#ifndef INSTRUCTIONSADVANCED_H
+#define INSTRUCTIONSADVANCED_H
+
+#include "ast.h"
+#include "llvmlayer.h"
+#include "pass/compilepass.h"
+
+#include <vector>
+
+namespace xreate {
+ namespace compilation {
+
+class Advanced {
+public:
+ Advanced(compilation::Context ctx);
+ llvm::Value* compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string ident = "");
+ 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
+ */
+ llvm::Value* compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
+ llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
+ llvm::Value* compileFoldInf(const Expression& fold, const std::string& ident="");
+ llvm::Value* compileLoopContext(const Expression& expression, const std::string& hintRetVar);
+ llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
+ llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
+ llvm::Value* compileConstantStringAsPChar(const std::string &data, const std::string& hintRetVar);
+ llvm::Value* compileConstantArray(const Expression &expr, const std::string& hintRetVar="");
+
+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
new file mode 100644
index 0000000..30a4c5b
--- /dev/null
+++ b/cpp/src/compilation/containers.cpp
@@ -0,0 +1,22 @@
+#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>());
+
+ default: assert(true);
+ }
+
+ assert(false && "Unknown declaration");
+ return nullptr;
+}
diff --git a/cpp/src/compilation/containers.h b/cpp/src/compilation/containers.h
new file mode 100644
index 0000000..e54334a
--- /dev/null
+++ b/cpp/src/compilation/containers.h
@@ -0,0 +1,187 @@
+#ifndef CODEINSTRUCTIONS_H
+#define CODEINSTRUCTIONS_H
+
+#include "ast.h"
+
+#include "llvmlayer.h"
+#include "pass/compilepass.h"
+#include "compilation/advanced.h"
+
+#include "query/context.h"
+#include "query/containers.h"
+#include "query/ptrvalid.h"
+
+namespace xreate {
+ namespace containers {
+
+using namespace llvm;
+
+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;
+
+template<>
+class IteratorForward<ON_THE_FLY> : public Iterator {
+private:
+ LLVMLayer* llvm;
+ const xreate::Symbol current;
+ const Symbol source;
+ const ImplementationLinkedList linkedlist;
+ CodeScope* const sourceScope;
+ //TODO initialize ans mark as const (three fields)
+ compilation::CodeScopeUnit* sourceUnit;
+ compilation::FunctionUnit* function; //TODO is used somewhere?
+ const Expression& sourceDecl;
+ compilation::Context context;
+ llvm::Type* sourceRawType =nullptr;
+
+public:
+ IteratorForward(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(new compilation::CodeScopeUnit(source.scope, ctx.function, ctx.pass)),
+ sourceDecl(CodeScope::findDeclaration(source)),
+ context(ctx)
+ {
+ }
+
+ llvm::Value* begin() {
+ switch(sourceDecl.op) {
+ case xreate::Operator::LIST:
+ {
+ sourceRawType = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ return llvm::ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 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* 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::getGlobalContext()), 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* get(Value* index,const std::string& hintRetVar="") override{
+ const Expression& currentDecl = CodeScope::findDeclaration(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->process(currentDecl);
+ return xreate::compilation::Advanced(context).compileArrayIndex(current, 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();
+ const std::string& varIn = currentDecl.getOperands()[0].getValueString();
+ std::string varEl = currentDecl.bindings[0];
+
+ const Symbol& symbIn = current.scope->findSymbol(varIn);
+ auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
+
+ Value* elIn = it->get(index, varEl);
+ compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
+ unitLoop->bindArg(elIn, std::move(varEl));
+ return unitLoop->compile();
+ }
+
+ case xreate::Operator::NONE: {
+ //TODO review iterator determination strategy for case of Expression::BINDING
+ assert(currentDecl.__state==Expression::IDENT);
+ const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
+ 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* advance(Value* index, const std::string& hintRetVar) override{
+ switch(sourceDecl.op)
+ {
+ case xreate::Operator::LIST:
+ case xreate::Operator::LIST_RANGE:
+ return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
+
+ default: break;
+ }
+
+ if (linkedlist){
+ ExpandedType tySource = llvm->ast->expandType(CodeScope::findDeclaration(source).type);
+ assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
+ assert(tySource->__operands.size());
+
+ return xreate::compilation::Advanced(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
+ }
+
+ assert(false && "Unknown declaration");
+ return nullptr;
+ }
+};
+}}
+
+#endif //CODEINSTRUCTIONS_H
diff --git a/cpp/src/compilation/instr-containers.h b/cpp/src/compilation/instr-containers.h
deleted file mode 100644
index 9fe4a08..0000000
--- a/cpp/src/compilation/instr-containers.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef CODEINSTRUCTIONS_H
-#define CODEINSTRUCTIONS_H
-
-#include "llvmlayer.h"
-#include "ast.h"
-#include <llvm/IR/Value.h>
-#include <vector>
-#include "pass/compilepass.h"
-
-namespace xreate {
- namespace containers {
-
-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* move(llvm::Value* index, const std::string& hintRetVar="")=0;
- virtual ~Iterator(){};
-
- static Iterator* create(compilation::Context context, const Symbol& var);
-};
-
-class Instructions {
-public:
- Instructions(compilation::Context ctx);
- llvm::Value* compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string ident = "");
- 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
- */
- llvm::Value* compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
- llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
- llvm::Value* compileLoopContext(const Expression& expression, const std::string& hintRetVar);
- llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
- llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
- llvm::Value* compileConstantStringAsPChar(const string &data, const std::string& hintRetVar);
- llvm::Value* compileConstantArray(const Expression &expr, const std::string& hintRetVar="");
-
-private:
- compilation::Context context;
- llvm::IntegerType* const tyNum;
-};
-
-
-
- }}
-
-#endif //CODEINSTRUCTIONS_H
-
-/*
- template<Operator Instruction>
- struct InstructionClasses {};
-
- template<>
- struct InstructionClasses<Operator::LIST> {
- typedef InstructionList Impl;
- };
-
- template<>
- struct InstructionClasses<Operator::MAP> {
- typedef InstructionMap Impl;
- };
-
- template<Operator Instruction>
- class CodeInstruction: public InstructionClasses<Instruction>::Impl
- {
- typedef typename InstructionClasses<Instruction>::Impl InstructionImpl;
-
- public:
- CodeInstruction(CodeScope* parent)
- : InstructionImpl(parent)
- {}
-
- llvm::Value *
- compileExpression(const Expression &expr, LLVMLayer &l, const std::string * const hintRetVar)
- {
- if (expr.op == Instruction)
- return InstructionImpl::compileDefault(expr, l, hintRetVar);
-
- return CodeScope::compileExpression(expr, l, hintRetVar);
- }
- };
-}
-*/
diff --git a/cpp/src/compilation/latecontextcompiler2.cpp b/cpp/src/compilation/latecontextcompiler2.cpp
index 5dccbc0..915f57b 100644
--- a/cpp/src/compilation/latecontextcompiler2.cpp
+++ b/cpp/src/compilation/latecontextcompiler2.cpp
@@ -1,119 +1,192 @@
/*
* LateContextCompiler2.cpp
*
* Created on: 10 февр. 2016
* Author: pgess
*/
+//TOTEST default variants - do not enable specialization context in order to check default variant invocation
+
#include "latecontextcompiler2.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "query/context.h"
#include <iostream>
-namespace xreate {
-
-LateContextCompiler2::LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p)
- : function(f), pass(p){}
-
-//TEST default variants - do not enable specialization context in order to check default variant invocation
-llvm::Value*
-LateContextCompiler2::findFunction(const std::string& calleeName, llvm::Function* specializationDefault){
- LLVMLayer* llvm = pass->man->llvm;
- llvm::IRBuilder<>& builder = llvm->builder;
- ContextQuery* context = pass->queryContext;
- const string& functionName = function->function->getName();
-
- const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
- const FunctionContextDemand& decisions = context->getFunctionDemand(functionName);
-
- assert(decisions.right.count(calleeName) && "Can't determine specialization of the function");
- size_t decisionIndex = decisions.right.at(calleeName);
- const ContextDomain& decisionDomain= context->getFunctionDomain(calleeName);
-
- llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- llvm::Type* tyCallee = specializationDefault->getType();
-
- llvm::BasicBlock* blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", this->function->raw);
-
- llvm::Value* decisionRaw = builder.CreateExtractValue(this->raw, llvm::ArrayRef<unsigned>{decisionIndex});
- llvm::SwitchInst* instrSwitch = builder.CreateSwitch(decisionRaw, blockDefault, decisionDomain.size());
-
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationEnd", this->function->raw);
- builder.SetInsertPoint(blockEpilog);
- llvm::PHINode *ret = llvm->builder.CreatePHI(tyCallee, decisionDomain.size(), "callee");
-
- for (const ManagedFnPtr& f: specializations){
- if (!f->guardContext.isValid()) continue;
- const Code& specCode = decisionDomain.getId(f->guardContext);
- llvm::ConstantInt* rawSpecCode = llvm::ConstantInt::get(ty32, specCode);
+using namespace std;
- llvm::BasicBlock* blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case+" + f->guardContext.getValueString(), this->function->raw);
- builder.SetInsertPoint(blockCase);
- builder.CreateBr(blockEpilog);
- ret->addIncoming(pass->getFunctionUnit(f)->compile(), blockCase);
+namespace xreate {
- instrSwitch->addCase(rawSpecCode, blockCase);
- }
+const string topicSpecializationAtom = "specialization";
+const string topicDependencyAtom = "dependency";
- //prepare default specialization
- builder.SetInsertPoint(blockDefault);
- builder.CreateBr(blockEpilog);
- ret->addIncoming(specializationDefault, blockDefault);
+LateContextCompiler2::LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p)
+ : function(f), pass(p){
+
+ ContextQuery* context = pass->queryContext;
+ __sizeOfDemand = context->getFunctionDemand(function->function->getName()).size();
+}
- builder.SetInsertPoint(blockEpilog);
- return ret;
+llvm::Function*
+LateContextCompiler2::findFunction(const std::string& calleeName, llvm::Function* specializationDefault, ScopePacked scopeCaller){
+ const string& functionName = function->function->getName();
+ ContextQuery* context = pass->queryContext;
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+
+ const FunctionDemand& demand = context->getFunctionDemand(functionName);
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
+
+ //independent decision:
+ Expression topic(Operator::CALL, {(Atom<Identifier_t>(string(topicSpecializationAtom))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
+ assert(demand.right.count(topic) && "Can't determine specialization for the function");
+ size_t topicId = demand.right.at(topic);
+ llvm::Value* topicDecisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
+
+ const Domain& specializationsDomain= context->getTopicDomain(topic);
+
+ std::vector<llvm::Function*> vectorVariants;
+ vectorVariants.reserve(specializationsDomain.size());
+ for (const ManagedFnPtr& f: specializations){
+ if (!f->guardContext.isValid()) continue;
+ const auto& variantId = specializationsDomain.getIdOptional(f->guardContext);
+ if (variantId){
+ if (vectorVariants.size() < *variantId + 1) {
+ vectorVariants.resize(*variantId + 1);
+ }
+
+ vectorVariants[*variantId] = pass->getFunctionUnit(f)->compile();
+ }
+ }
+
+ return
+ llvm::dyn_cast<llvm::Function>(
+ compileDecisionSelectorAsSwitch(topicDecisionRaw, vectorVariants, specializationDefault));
}
llvm::Value*
-LateContextCompiler2::compileArgument(const std::string& callee, ScopePacked scopeOuter){
- llvm::IRBuilder<>& builder = pass->man->llvm->builder;
- ContextQuery* context = pass->queryContext;
- const string& functionName = function->function->getName();
- const map<string, Expression>& dictStaticDecisions = context->getStaticDecisions(scopeOuter);
-
- const FunctionContextDemand& decisionsCallee = context->getFunctionDemand(callee);
- const FunctionContextDemand& decisionsSelf = context->getFunctionDemand(functionName);
-
- llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- llvm::Type* tyDemand = llvm::ArrayType::get(ty32, decisionsCallee.size());
-
- //builder.CreateAlloca(tyDemand, llvm::ConstantInt::get(ty32, 1));
- llvm::Value* res = llvm::ConstantArray::getNullValue(tyDemand);
+LateContextCompiler2::compileContextArgument(const std::string& callee, ScopePacked scopeCaller){
+ const std::string& atomDependentDecision = Config::get("clasp.context.decisions.dependent");
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ ContextQuery* context = pass->queryContext;
+
+ const string& functionName = function->function->getName();
+ const Decisions& dictStaticDecisions = context->getFinalDecisions(scopeCaller);
+
+ const FunctionDemand& demandCallee = context->getFunctionDemand(callee);
+ const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
+
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, demandCallee.size());
+
+ //builder.CreateAlloca(tyDemand, llvm::ConstantInt::get(ty32, 1));
+ llvm::Value* res = llvm::ConstantArray::getNullValue(tyDemand);
+
+ for (size_t i=0, size = demandCallee.size(); i<size; ++i){
+ const Expression& topic = demandCallee.left.at(i);
+ llvm::Value* decisionRaw;
+
+ if (demandSelf.right.count(topic)){
+ //TOTEST decision propagation
+ //propagate decision
+ const size_t& topicId = demandSelf.right.at(topic);
+ decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
+
+ } else if (dictStaticDecisions.count(topic)){
+ //static final decision:
+ const Expression& decision = dictStaticDecisions.at(topic);
+ const Domain& domainOfTopic = context->getTopicDomain(topic);
+ const DomainId& decisionCode = domainOfTopic.getId(decision);
+ decisionRaw = llvm::ConstantInt::get(ty32, decisionCode);
+
+ } else {
+ //dependent decision
+ decisionRaw = compileDependentDecision(topic, scopeCaller);
+ }
+
+ res = builder.CreateInsertValue(res, decisionRaw, llvm::ArrayRef<unsigned>{(unsigned) i});
+ }
+
+ return res;
+}
- for (size_t i=0, size = decisionsCallee.size(); i<size; ++i){
- const string& key = decisionsCallee.left.at(i);
+llvm::Value*
+LateContextCompiler2::compileDependentDecision(const Expression& topic, ScopePacked scopeCaller){
+ const string& functionName = function->function->getName();
+ ContextQuery* context = pass->queryContext;
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
+ const Expression topicDependency = Expression(Operator::CALL, {Atom<Identifier_t>(string(topicDependencyAtom)), topic, Atom<Number_t>(scopeCaller)});
+
+ const Domain& demandOfTopic = context->getTopicDomain(topic);
+ const Domain& domainOfTopicDependency = context->getTopicDomain(topicDependency);
+
+ //dependent decision
+ vector<llvm::Value*> vectorDecisions(domainOfTopicDependency.size(), llvm::UndefValue::get(ty32));
+ for (const std::pair<Expression, Expression>& entry: context->getDependentDecision(scopeCaller,topic)){
+ vectorDecisions[domainOfTopicDependency.getId(entry.first)]= llvm::ConstantInt::get(ty32, demandOfTopic.getId(entry.second));
+ }
+
+ size_t topicDependencyId = demandSelf.right.at(topicDependency);
+ llvm::Value* decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicDependencyId});
+
+ auto result = compileDecisionSelector(decisionRaw, vectorDecisions);
+
+ return result;
+}
- if (dictStaticDecisions.count(key)){
- const Expression& decision = dictStaticDecisions.at(key);
- const Domain& dom = context->getFunctionDomain(key);
- const Code& decisionCode = dom.getId(decision);
+llvm::Value*
+LateContextCompiler2::compileDecisionSelector(llvm::Value* selector, std::vector<llvm::Value*> vectorVariants, llvm::Value* variantDefault){
+ //TODO implement variantDefault;
+ assert(vectorVariants.size()>0);
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- res = builder.CreateInsertValue(res, llvm::ConstantInt::get(ty32, decisionCode), llvm::ArrayRef<unsigned>{i});
- continue;
- }
+ llvm::Type* tyElement = vectorVariants[0]->getType();
+ llvm::Type* tyVariants = llvm::VectorType::get(tyElement, vectorVariants.size());
+ llvm::Value* vectorRaw = llvm::ConstantVector::getNullValue(tyVariants);
+
- //TEST decision propagtion
- const size_t& decisionIndex = decisionsSelf.right.at(key);
- llvm::Value* decision = builder.CreateExtractValue(this->raw, llvm::ArrayRef<unsigned>{decisionIndex});
- res = builder.CreateInsertElement(res, llvm::ConstantInt::get(ty32, i), decision);
- }
+ for(DomainId i=0; i<vectorVariants.size(); ++i){
+ vectorRaw = builder.CreateInsertElement(vectorRaw, vectorVariants[i], llvm::ConstantInt::get(ty32, i));
+ }
- return res;
+ return builder.CreateExtractElement(vectorRaw, selector);
}
-size_t
-LateContextCompiler2::getFunctionVariantsSize() const {
- ContextQuery* context = pass->queryContext;
-
- return context->getFunctionDomain(function->function->getName()).size();
+llvm::Value*
+LateContextCompiler2::compileDecisionSelectorAsSwitch(llvm::Value* selector, std::vector<llvm::Function*> vectorVariants, llvm::Value* variantDefault){
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ llvm::BasicBlock* blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", this->function->raw);
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "VariantDeterminationEnd", this->function->raw);
+
+ llvm::SwitchInst* instrSwitch = builder.CreateSwitch(selector, blockDefault, vectorVariants.size());
+
+ builder.SetInsertPoint(blockEpilog);
+ llvm::PHINode *result = builder.CreatePHI(variantDefault->getType(), vectorVariants.size(), "callee");
+
+ for (size_t i=0; i<vectorVariants.size(); ++i){
+ llvm::BasicBlock* blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "", this->function->raw);
+ builder.SetInsertPoint(blockCase);
+ builder.CreateBr(blockEpilog);
+ result->addIncoming(vectorVariants[i], blockCase);
+ instrSwitch->addCase(llvm::ConstantInt::get(ty32, i), blockCase);
+ }
+
+ builder.SetInsertPoint(blockDefault);
+ builder.CreateBr(blockEpilog);
+ result->addIncoming(variantDefault, blockDefault);
+
+ builder.SetInsertPoint(blockEpilog);
+ return result;
}
size_t
LateContextCompiler2::getFunctionDemandSize() const {
- ContextQuery* context = pass->queryContext;
-
- return context->getFunctionDemand(function->function->getName()).size();
+ return __sizeOfDemand;
}
} /* namespace xreate */
diff --git a/cpp/src/compilation/latecontextcompiler2.h b/cpp/src/compilation/latecontextcompiler2.h
index 4ef802a..791d8d4 100644
--- a/cpp/src/compilation/latecontextcompiler2.h
+++ b/cpp/src/compilation/latecontextcompiler2.h
@@ -1,50 +1,54 @@
/*
* LateContextCompiler2.h
*
* Created on: 10 февр. 2016
* Author: pgess
*/
+//TOTEST compile several context arguments
#ifndef LATECONTEXTCOMPILER2_H_
#define LATECONTEXTCOMPILER2_H_
#include "serialization.h"
namespace llvm {
class Value;
class Function;
}
namespace xreate {
class CompilePass;
namespace compilation {
class FunctionUnit;
}}
namespace xreate {
typedef unsigned int ScopePacked;
class LateContextCompiler2 {
public:
- llvm::Value* raw = nullptr;
+ llvm::Value* rawContextArgument = nullptr;
LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p);
- llvm::Value* findFunction(const std::string& calleeName, llvm::Function* specializationDefault);
- llvm::Value* compileArgument(const std::string& callee, ScopePacked scopeOuter);
- size_t getFunctionVariantsSize() const;
- size_t getFunctionDemandSize() const;
+ llvm::Function* findFunction(const std::string& calleeName, llvm::Function* specializationDefault, ScopePacked scopeCaller);
+ llvm::Value* compileContextArgument(const std::string& callee, ScopePacked scopeCaller);
+ size_t getFunctionDemandSize() const;
private:
- typedef ExpressionSerialization<RequirementIntegralCode>::Code Code;
+ typedef ExpressionSerialization<RequirementIntegralCode>::Code DomainId;
typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
//boost::bimap<size_t, std::string> __decisions;
//std::vector<Domain> __scheme;
compilation::FunctionUnit* function;
CompilePass* pass;
+ size_t __sizeOfDemand;
+
+ llvm::Value* compileDependentDecision(const Expression& topic, ScopePacked scopeCaller);
+ llvm::Value* compileDecisionSelector(llvm::Value* selector, std::vector<llvm::Value*> vectorVariants, llvm::Value* variantDefault=nullptr);
+ llvm::Value* compileDecisionSelectorAsSwitch(llvm::Value* selector, std::vector<llvm::Function*> vectorVariants, llvm::Value* variantDefault);
};
-
} /* namespace xreate */
#endif /* LATECONTEXTCOMPILER2_H_ */
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
new file mode 100644
index 0000000..fceda31
--- /dev/null
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -0,0 +1,354 @@
+/*
+ * File: targetinterpretation.cpp
+ * Author: pgess
+ *
+ * Created on June 29, 2016, 6:45 PM
+ */
+
+#include "compilation/targetinterpretation.h"
+#include "pass/interpretationpass.h"
+
+using namespace std;
+
+namespace xreate{ namespace compilation {
+
+ const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
+ const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
+
+//Expression
+//InterpretationScope::compile(const Expression& expression){}
+
+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(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;
+}
+
+llvm::Value*
+InterpretationScope::compileHybrid(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 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];
+ const Symbol& symbolEl = scopeBody->findSymbol(nameEl);
+ const std::string& idAccum = expression.bindings[1];
+ llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
+ compilation::CodeScopeUnit* unitBody = context.function->getScopeUnit(scopeBody);
+ InterpretationScope* intrBody = function->getScope(scopeBody);
+ const std::vector<Expression> elementsInput= exprInput.getOperands();
+
+ for (size_t i=0; i<elementsInput.size(); ++i){
+ Expression exprElement = elementsInput[i];
+
+ unitBody->reset();
+
+ intrBody->bindArg(exprElement, nameEl);
+ unitBody->overrideDeclaration(symbolEl, move(exprElement));
+ unitBody->bindArg(rawAccum, string(idAccum));
+
+ rawAccum = unitBody->compile();
+ }
+
+ return rawAccum;
+ }
+
+ default: break;
+ }
+
+ assert(false&& "Unknown hybrid operator");
+ return nullptr;
+}
+
+llvm::Value*
+InterpretationScope::compile(const Expression& expression, const Context& context){
+ const InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression);
+
+ if (data.op != InterpretationOperator::NONE){
+ return compileHybrid(data.op, expression, context);
+ }
+
+ Expression result = process(expression);
+ return context.scope->processLowlevel(result);
+}
+
+Expression
+InterpretationScope::process(const Expression& expression){
+ switch (expression.__state){
+ case Expression::VARIANT:
+ case Expression::INVALID:
+ assert(false);
+
+ case Expression::NUMBER:
+ case Expression::STRING:
+ return expression;
+
+ case Expression::IDENT:{
+ const std::string &ident = expression.getValueString();
+
+ Symbol s = scope->findSymbol(ident);
+ 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);
+ InterpretatonFunction* 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::IF:{
+ CodeScope* scopeResult = processOperatorIf(expression);
+ return function->getScope(scopeResult)->processScope();
+ }
+
+ case Operator::SWITCH: {
+ CodeScope* scopeResult = processOperatorSwitch(expression);
+ return function->getScope(scopeResult)->processScope();
+ }
+
+ case Operator::INDEX: {
+ const Expression& exprKey = process(expression.operands[0]);
+ const Expression& exprData = processSymbol(scope->findSymbol(expression.getValueString()));
+
+
+ if (exprKey.__state == Expression::STRING){
+ const string& key = exprKey.getValueString();
+ assert(exprData.__indexBindings.count(key));
+
+ return exprData.operands[exprData.__indexBindings.at(key)];
+ }
+
+ if (exprKey.__state == Expression::NUMBER){
+ int key = exprKey.getValueDouble();
+ return exprData.operands[key];
+ }
+
+ assert(false);
+ }
+
+ 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->bindArg(exprInput.getOperands()[i], argEl);
+ body->bindArg(accum, argAccum);
+
+ accum = body->processScope();
+ }
+
+ return accum;
+ }
+
+// case Operator::MAP: {
+// break;
+// }
+
+ default: break;
+ }
+
+ return expression;
+}
+
+InterpretatonFunction::InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
+ : Function<TargetInterpretation>(function, target)
+{}
+
+Expression
+InterpretatonFunction::process(const std::vector<Expression>& args){
+ InterpretationScope* body = getScope(__function->__entry);
+
+ for(size_t i=0, size = args.size(); i<size; ++i) {
+ body->bindArg(args.at(i), string(body->scope->__bindings.at(i)));
+ }
+
+ return body->processScope();
+}
+
+InterpretatonFunction*
+TargetInterpretation::getFunction(const PIFSignature& sig){
+ return __functions.find(sig);
+}
+
+InterpretationScope*
+TargetInterpretation::transformContext(const Context& c){
+ return this->getFunction(c.function->function)->getScope(c.scope->scope);
+}
+
+llvm::Value*
+TargetInterpretation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
+ return raw;
+}
+
+Expression
+TargetInterpretation::transform(const Expression& expression, const Context& ctx){
+ return transformContext(ctx)->process(expression);
+}
+
+llvm::Value*
+TargetInterpretation::compile(const Expression& expression, const Context& ctx){
+ return transformContext(ctx)->compile(expression, ctx);
+}
+
+bool
+TargetInterpretation::isAcceptable(const Expression& expression){
+ const InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression, {BOTH, NONE});
+
+ return (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
+}
+
+}}
+
+ //Partial function interpretation
+llvm::Value*
+InterpretationScope::compilePartialFnCall(const Expression& expression, const Context& context){
+ const std::string &fnName = expression.getValueString();
+ ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
+ context.pass->getFunctionUnit(fnAst)
+
+ intrBody->bindArg(exprElement, nameEl);
+ unitBody->overrideDeclaration(symbolEl, move(exprElement));
+}
+
+class PartialInterpretationScopeDecorator(){
+ void compile(){
+
+ }
+
+ void findFunction(){
+
+ }
+};
+
+template<class Parent>
+class PartialInterpretationFunctionDecorator: public Parent{
+
+protected:
+ void recognizeArguments(){
+ argsReal.reserve(entry->__bindings.size());
+
+ for(size_t no=0, size=entry->__bindings.size(); no < size; ++no){
+ const std::string& argName = entry->__bindings[no];
+ const Expression& arg = entry->findDeclaration(entry->findSymbol(argName));
+
+ InterpretationResolution res = recognizeTags(arg.tags);
+ if (res != INTR_ONLY){
+ argsReal.push_back(arg);
+ }
+ }
+ }
+
+ std::vector<llvm::Type*> prepareArguments(){
+ std::vector<llvm::Type*> signature;
+
+ for(size_t no=0, size=argsReal.size(); no < size; ++no){
+ signature.push_back(llvm->toLLVMType(ast->expandType(argsReal[no].type)));
+ }
+ }
+
+ void prepareBindings(){
+ // bindings from argsReal
+ }
+
+private:
+ std::vector<Expression> argsReal;
+};
+
+template<class Parent>
+class PartialInterpretationCallStatement: public Parent {
+ PartialInterpretationCallStatement(){
+
+ }
+}
\ No newline at end of file
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
new file mode 100644
index 0000000..94c44d8
--- /dev/null
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -0,0 +1,100 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * File: targetstatic.h
+ * Author: pgess
+ *
+ * Created on July 2, 2016, 1:25 PM
+ */
+
+#ifndef TARGETSTATIC_H
+#define TARGETSTATIC_H
+
+#include "ast.h"
+#include "compilation/targets.h"
+#include "transformations.h"
+#include "pass/interpretationpass.h"
+
+namespace xreate{ namespace compilation {
+
+class TargetInterpretation;
+class InterpretationScope;
+class InterpretatonFunction;
+
+ template <>
+ struct TargetInfo<TargetInterpretation> {
+ typedef Expression Result;
+ typedef InterpretationScope Scope;
+ typedef InterpretatonFunction Function;
+ };
+
+ template<>
+ struct TransformerInfo<TargetInterpretation> {
+ static const int id = 1;
+ };
+
+class InterpretationScope: public Scope<TargetInterpretation>{
+ typedef Scope<TargetInterpretation> Parent;
+
+public:
+ InterpretationScope(CodeScope* scope, Function<TargetInterpretation>* f): Parent(scope, f) {}
+ Expression process(const Expression& expression) override;
+
+ llvm::Value* compile(const Expression& expression, const Context& context);
+
+private:
+ llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context);
+ llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
+
+ CodeScope* processOperatorIf(const Expression& expression);
+ CodeScope* processOperatorSwitch(const Expression& expression);
+
+};
+
+class InterpretatonFunction: public Function<TargetInterpretation>{
+ public:
+ PIFSignature signature;
+
+ InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target);
+ Expression process(const std::vector<Expression>& args);
+};
+
+/*
+ * Partially interpreted function signature
+ */
+struct PIFSignature{
+ ManagedFnPtr declaration;
+ std::vector<Expression> bindings;
+};
+
+class TargetInterpretation: public Transformer, public Target<TargetInterpretation>{
+public:
+ TargetInterpretation(AST* root): Target<TargetInterpretation>(root){}
+
+ //transformer:
+public:
+ virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
+ virtual Expression transform(const Expression& expression, const Context& ctx) override;
+ virtual bool isAcceptable(const Expression& expression) override;
+
+ //target:
+public:
+ InterpretatonFunction* getFunction(const ManagedFnPtr& function);
+private:
+ std::set<InterpretationFunction*> __functions;
+
+ //self:
+public:
+ llvm::Value* compile(const Expression& expression, const Context& ctx);
+private:
+ InterpretationScope* transformContext(const Context& c);
+};
+
+}}
+
+#endif /* TARGETSTATIC_H */
+
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
new file mode 100644
index 0000000..fb10bec
--- /dev/null
+++ b/cpp/src/compilation/targets.h
@@ -0,0 +1,146 @@
+/*
+ * File: targetabstract.h
+ * Author: pgess
+ *
+ * Created on July 2, 2016, 1:25 PM
+ */
+
+#ifndef TARGETABSTRACT_H
+#define TARGETABSTRACT_H
+#include "ast.h"
+
+#include <boost/optional.hpp>
+#include <map>
+
+namespace xreate{ namespace compilation {
+
+template <typename ConcreteTarget>
+struct TargetInfo{
+ //typedef Result
+ //typedef Function
+ //typedef Scope
+};
+
+template<typename ConcreteTarget>
+class Function;
+
+template<typename ConcreteTarget>
+class Target;
+
+template<typename ConcreteTarget>
+class Scope{
+public:
+ CodeScope* scope;
+
+ typename TargetInfo<ConcreteTarget>::Result
+ processSymbol(const Symbol& s){
+ CodeScope* scope = s.scope;
+ typename TargetInfo<ConcreteTarget>::Scope* self = function->getScope(scope);
+
+ if (self->__bindings.count(s.identifier)) {
+ return self->__bindings[s.identifier];
+ }
+
+ const Expression& declaration = CodeScope::findDeclaration(s);
+ if (!declaration.isDefined()){
+ assert(false); //for bindings there should be result already
+ }
+
+ return self->__bindings[s.identifier] = self->process(declaration);
+ }
+
+ typename TargetInfo<ConcreteTarget>::Result
+ processScope() {
+ if (raw) return *raw;
+
+ raw = process(scope->__body);
+ return *raw;
+ }
+
+ virtual typename TargetInfo<ConcreteTarget>::Result
+ process(const Expression& expression)=0;
+
+ Scope(CodeScope* codeScope, Function<ConcreteTarget>* f)
+ : scope(codeScope), function(f) {}
+
+ virtual ~Scope(){}
+
+ void
+ bindArg(typename TargetInfo<ConcreteTarget>::Result arg, const std::string& name){
+ assert(scope->__identifiers.count(name));
+
+ VID id = scope->__identifiers.at(name);
+ __bindings[id] = arg;
+
+ //reset the result if any:
+ raw.reset();
+ }
+
+protected:
+ Function<ConcreteTarget>* function;
+ std::map<VID, typename TargetInfo<ConcreteTarget>::Result> __bindings;
+ typename boost::optional<typename TargetInfo<ConcreteTarget>::Result> raw;
+
+ //ResultType findFunction(const std::string& callee);
+};
+
+template<typename ConcreteTarget>
+class Function{
+ typedef typename TargetInfo<ConcreteTarget>::Result Result;
+
+public:
+ Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
+ : man(target), __function(function) {}
+
+ typename TargetInfo<ConcreteTarget>::Scope*
+ getScope(CodeScope* scope){
+ if (!__scopes.count(scope)){
+ typename TargetInfo<ConcreteTarget>::Scope* unit = new typename TargetInfo<ConcreteTarget>::Scope(scope, this);
+ __scopes.emplace(scope, std::unique_ptr<typename TargetInfo<ConcreteTarget>::Scope>(unit));
+ }
+
+ return __scopes.at(scope).get();
+ }
+
+ virtual Result
+ process(const std::vector<Result>& args)=0;
+
+ Target<ConcreteTarget>* man;
+
+protected:
+ ManagedFnPtr __function;
+
+
+ std::map<CodeScope*, std::unique_ptr<typename TargetInfo<ConcreteTarget>::Scope>> __scopes;
+};
+
+template<typename ConcreteTarget>
+class Target {
+ typedef typename TargetInfo<ConcreteTarget>::Function ConcreteFunction;
+
+ public:
+ Target(AST* root): ast(root){}
+
+ ConcreteFunction*
+ getFunction(const ManagedFnPtr& function){
+ unsigned int id = function.id();
+
+ if (!__functions.count(id)){
+ ConcreteFunction* unit = new ConcreteFunction(function, this);
+ __functions.emplace(id, std::unique_ptr<ConcreteFunction>(unit));
+ return unit;
+ }
+
+ return __functions.at(id).get();
+ }
+
+ AST* ast;
+
+ private:
+ std::map<unsigned int, std::unique_ptr<ConcreteFunction>> __functions;
+};
+
+}}
+
+#endif /* TARGETABSTRACT_H */
+
diff --git a/cpp/src/compilation/transformations.cpp b/cpp/src/compilation/transformations.cpp
new file mode 100644
index 0000000..d77ca83
--- /dev/null
+++ b/cpp/src/compilation/transformations.cpp
@@ -0,0 +1,143 @@
+/*
+ * File: Transformations.cpp
+ * Author: pgess
+ *
+ * Created on June 18, 2016, 6:23 PM
+ */
+
+#include "compilation/transformations.h"
+#include "pass/compilepass.h"
+#include "llvmlayer.h"
+#include <llvm/IR/Value.h>
+
+using namespace llvm;
+
+namespace xreate { namespace compilation {
+
+Transformations::Transformations(CompilePass* passCompilation): pass(passCompilation) {
+}
+
+void
+Transformations::subscribe(const std::string& annotation, int handler){
+ __subscriptions.emplace(annotation, handler);
+}
+
+bool
+Transformations::isAcceptable(const Expression& expression){
+ //check subscription based on expression attachments
+ if (Attachments::get<Expression, Transformations>(expression, {false, 0}).flagSubscribed){
+ return true;
+ }
+
+ //subscription based on expression annotations;
+ if (expression.tags.size() == 0) return false;
+
+ for (auto tag: expression.tags) {
+ if (__subscriptions.count(tag.first)){
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Expression
+Transformations::transform(const Expression& expression, const Context& ctx){
+ Expression result = expression;
+
+ for (auto handler: getAppropriateTransformers(expression)){
+ result = handler->transform(result, ctx);
+ }
+
+ return result;
+}
+
+llvm::Value*
+Transformations::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
+ for (auto handler: getAppropriateTransformers(expression)){
+ raw = handler->transform(expression, raw, ctx);
+ }
+
+ return raw;
+}
+
+std::list<Transformer*>
+Transformations::getAppropriateTransformers(const Expression& expression){
+
+ std::list<Transformer*> result;
+
+ for (auto tag: expression.tags) {
+ if (__subscriptions.count(tag.first)){
+ auto handlers = __subscriptions.equal_range(tag.first);
+
+ for (auto handlerIt=handlers.first; handlerIt!= handlers.second; ++handlerIt){
+ Transformer* handler = __transformers[handlerIt->second];
+
+ if (handler->isAcceptable(expression)){
+ result.push_back(handler);
+ }
+ }
+ }
+ }
+
+ auto subscriberInternal = Attachments::get<Expression, Transformations>(expression, {false, 0});
+ if (subscriberInternal.flagSubscribed){
+ result.push_back(__transformers[subscriberInternal.subscriberId]);
+ }
+
+ return result;
+}
+
+TransformerSaturation::TransformerSaturation(Transformations* man)
+ : __man(man) {
+
+ man->subscribe("break", TransformerInfo<TransformerSaturation>::id);
+}
+
+bool
+TransformerSaturation::isAcceptable(const Expression& expression){
+ return true;
+}
+
+bool
+TransformerSaturation::exists() const{
+ return __block != nullptr;
+}
+
+llvm::Value*
+TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
+ __block = __man->pass->man->llvm->builder.GetInsertBlock();
+
+ return raw;
+}
+
+llvm::BasicBlock*
+TransformerSaturation::getBlock() const{
+ return __block;
+}
+
+void
+TransformerSaturation::inject(llvm::BasicBlock* blockAllocation, llvm::BasicBlock* blockExit, compilation::Context context){
+ llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ llvm::Value* valueConstOne = llvm::ConstantInt::get(tyInt1, 1);
+ llvm::Value* valueConstFalse = llvm::ConstantInt::get(tyInt1, 0);
+
+ //allocation of saturation flag
+ IRBuilder<> builderAlloca(blockAllocation, blockAllocation->getFirstInsertionPt());
+ llvm::Value* flagSaturation = builderAlloca.CreateAlloca(tyInt1, valueConstOne, "flagSaturation");
+ builderAlloca.CreateStore(valueConstFalse, flagSaturation, true);
+
+ //set up saturation flag
+ llvm::BasicBlock* blockSaturation = __block;
+ IRBuilder<> builderSaturation(blockSaturation, blockSaturation->getFirstInsertionPt());
+ builderSaturation.CreateStore(valueConstOne, flagSaturation, true);
+
+ //check saturation flag:
+ //TODO remove blockContinue, receive from caller block to continue.
+ llvm::BasicBlock *blockContinue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "continue", context.function->raw);
+ context.pass->man->llvm->builder.CreateCondBr(context.pass->man->llvm->builder.CreateLoad(flagSaturation), blockExit, blockContinue);
+
+ context.pass->man->llvm->builder.SetInsertPoint(blockContinue);
+}
+
+}}
\ No newline at end of file
diff --git a/cpp/src/compilation/transformations.h b/cpp/src/compilation/transformations.h
new file mode 100644
index 0000000..daec0bf
--- /dev/null
+++ b/cpp/src/compilation/transformations.h
@@ -0,0 +1,119 @@
+/*
+ * File: Transformations.h
+ * Author: pgess
+ *
+ * Created on June 18, 2016, 6:23 PM
+ */
+
+#ifndef TRANSFORMATIONS_H
+#define TRANSFORMATIONS_H
+
+#include "ast.h"
+#include "pass/compilepass.h"
+#include "attachments.h"
+
+namespace llvm {
+ class BasicBlock;
+}
+
+namespace xreate { namespace compilation {
+
+ class Transformer{
+ public:
+ virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx)=0;
+ virtual Expression transform(const Expression& expression, const Context& ctx){return expression;}
+ virtual bool isAcceptable(const Expression& expression)=0;
+
+ virtual ~Transformer(){};
+ };
+
+ class TransformerSaturation: public Transformer{
+ public:
+ llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx);
+ bool isAcceptable(const Expression& expression);
+
+ TransformerSaturation(Transformations*);
+ llvm::BasicBlock* getBlock() const;
+ bool exists() const;
+ void inject(llvm::BasicBlock* blockAllocation, llvm::BasicBlock* blockExit, compilation::Context context);
+
+ private:
+ llvm::BasicBlock* __block = nullptr;
+ Transformations* __man;
+ };
+
+ template <class TransformerType>
+ struct TransformerInfo {
+ //static const int id = 1; (next vacant id)
+ };
+
+ template <>
+ struct TransformerInfo<TransformerSaturation> {
+ static const int id = 0;
+ };
+
+ class Transformations;
+
+ struct SubscriberInfo{
+ bool flagSubscribed;
+ int subscriberId;
+ };
+
+ class Transformations: public Transformer {
+ public:
+ xreate::CompilePass* pass;
+
+ bool isAcceptable(const Expression& expression);
+ llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
+ Expression transform(const Expression& expression, const Context& ctx) override;
+
+ Transformations(CompilePass*);
+ void subscribe(const std::string& annotation, int handler);
+
+ template<class TransformerType>
+ void registerTransformer(TransformerType* t){
+ const int id = TransformerInfo<TransformerType>::id;
+
+ __transformers[id] = t;
+ }
+
+ template<class Holder, class TransformerType>
+ static void subscribe(const Holder& holder){
+ //assert(! Attachments::exists<Holder, Transformations>());
+
+ const int id = TransformerInfo<TransformerType>::id;
+
+ if (Attachments::exists<Holder, Transformations>(holder)){
+ const int idOld = Attachments::get<Holder, Transformations>(holder).subscriberId;
+ assert(idOld == id);
+ return;
+ }
+
+ Attachments::put<Holder, Transformations>(holder, {true, id});
+ }
+
+ template <class TransformerType>
+ TransformerType* get(){
+ const int id = TransformerInfo<TransformerType>::id;
+ return static_cast<TransformerType*>(__transformers.at(id));
+ }
+
+ private:
+ std::map<int, Transformer*> __transformers;
+ std::multimap<std::string, int> __subscriptions;
+
+ std::list<Transformer*> getAppropriateTransformers(const Expression& expression);
+ };
+}}
+
+namespace xreate {
+ template<>
+ struct AttachmentsDict<compilation::Transformations>
+ {
+ typedef xreate::compilation::SubscriberInfo Data;
+ static const unsigned int key = 4;
+ };
+}
+
+#endif /* TRANSFORMATIONS_H */
+
diff --git a/cpp/src/contextrule.cpp b/cpp/src/contextrule.cpp
index 6ae4fc4..af3c84e 100644
--- a/cpp/src/contextrule.cpp
+++ b/cpp/src/contextrule.cpp
@@ -1,52 +1,53 @@
/*
* contextrule.cpp
*
* Created on: Jan 2, 2016
* Author: pgess
*/
#include "contextrule.h"
#include "clasplayer.h"
+#include "analysis/aux.h"
#include <boost/format.hpp>
using namespace xreate;
using namespace std;
ContextRule::ContextRule(const Expression& rule) {
assert(rule.op == Operator::CONTEXT_RULE);
assert(rule.operands.size() == 3);
head = rule.operands.at(0);
guards = rule.operands.at(1);
body = rule.operands.at(2);
}
std::string
ContextRule::compile(const ScopePacked& scopeId) const{
const string prolog =
" %context rule visibility implemenetation\n"
"context_rule_visibility(X, Y) :- X=Y, scope(X), scope(Y).\n"
"context_rule_visibility(X, Y) :- cfa_parent(X, scope(Y)), scope(X), scope(Y).\n";
- list<string>repHead_ = ClaspLayer::compile(head);
+ list<string>repHead_ = xreate::analysis::compile(head);
assert(repHead_.size() == 1);
- list<string>repGuards_ = ClaspLayer::compile(guards);
+ list<string>repGuards_ = xreate::analysis::compile(guards);
assert(repGuards_.size() == 1);
- list<string>repBody_ = ClaspLayer::compile(body);
+ list<string>repBody_ = xreate::analysis::compile(body);
assert(repBody_.size() == 1);
const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
boost::format formatContextVisibility("context_rule_visibility(ScopeX, %1%)");
- boost::format formatScopeBind(atomBindingScope + "(ScopeX, %1%)");
+ boost::format formatScopeBind(atomBindingScope + "(ScopeX, %1%, Linkage)");
const string& repHead = str(formatScopeBind % repHead_.front());
const string& repGuards = str(formatScopeBind % repGuards_.front());
const string& repVisibility = str(formatContextVisibility % scopeId);
boost::format formatRule("%1%:- %2%, %3%, %4%.");
return prolog + str(formatRule % repHead % repGuards % repBody_.front() % repVisibility);
}
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index 7eac8f0..ec136fd 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,36 +1,35 @@
#include "abstractpass.h"
#include "attachments.h"
#include "passmanager.h"
using namespace std;
namespace xreate {
template<>
- void defaultValue(){};
+ void defaultValue<void>(){}
- void AbstractPassBase::finish()
- {}
+ void AbstractPassBase::finish(){}
AbstractPassBase::AbstractPassBase(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const std::string& ident, PassContext context)
{
const Symbol& symbol = context.scope->findSymbol(ident);
if (__visitedSymbols.isCached(symbol))
return;
- if (CodeScope::hasDeclaration(symbol)) {
- __visitedSymbols.setCachedValue(symbol);
+ __visitedSymbols.setCachedValue(symbol);
+ const Expression& declaration = CodeScope::findDeclaration(symbol);
- PassContext context2 = context;
- context2.scope = symbol.scope;
- process(CodeScope::findDeclaration(symbol), context2, ident);
+ if (declaration.isDefined()){
+ PassContext context2 = context.updateScope(symbol.scope);
+ process(declaration, context2, ident);
}
}
}
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 8e4aef4..5595004 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,176 +1,194 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
#include "passmanager.h"
#include<iostream>
-using namespace std;
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
PassContext&& updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return std::move(context2);
}
~PassContext(){}
};
class AbstractPassBase {
public:
AbstractPassBase(PassManager* manager);
virtual void run()=0;
virtual void finish();
PassManager* man;
};
template<class Output>
Output defaultValue();
+
+ template<>
+ void defaultValue<void>();
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->emplace(symbol, value);
return value;
}
Output getCachedValue(const Symbol& symbol){
assert(this->count(symbol));
return this->at(symbol);
}
};
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){
}
};
template<class Output>
class AbstractPass: public AbstractPassBase {
- private:
+
SymbolCache<Output> __visitedSymbols;
+ protected:
Output processSymbol(const std::string& ident, PassContext context){
const Symbol& symbol = context.scope->findSymbol(ident);
if (__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
- if (CodeScope::hasDeclaration(symbol)) {
- PassContext context2 = context;
- context2.scope = symbol.scope;
- Output&& result = process(CodeScope::findDeclaration(symbol), context2, ident);
+
+ const Expression& declaration = CodeScope::findDeclaration(symbol);
+ if (declaration.isDefined()){
+ PassContext context2 = context.updateScope(symbol.scope);
+
+ Output&& result = process(declaration, context2, ident);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
-
+
return defaultValue<Output>();
}
+
+ SymbolCache<Output>& getSymbolCache(){
+ return __visitedSymbols;
+ }
+
+
public:
AbstractPass(PassManager* manager)
: AbstractPassBase(manager){}
-
+
//NOTE implement processFnCall
virtual void processFnCall(ManagedFnPtr function, PassContext context)
{}
virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context)
{}
virtual void process(ManagedRulePtr rule)
{}
virtual Output process(ManagedFnPtr function){
+ const Symbol& symbolFunction{0, function->getEntryScope()};
+
+ if (__visitedSymbols.isCached(symbolFunction))
+ return __visitedSymbols.getCachedValue(symbolFunction);
+
PassContext context;
context.function = function;
-
+
return process(function->getEntryScope(), context);
}
virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
context.scope = scope;
return process(scope->__body, context);
}
virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
switch (expression.__state) {
case Expression::COMPOUND:
assert(expression.op != Operator::MAP || (expression.op == Operator::MAP && expression.blocks.size()));
+ //TODO there are discrepancies for SWITCH CASE scopes.case body parent scope differs from context.scope.
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
+ //
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL) {
const std::string &calleeName = expression.getValueString();
- list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
+ std::list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
if (callees.size() == 1 && callees.front()){
processFnCall(callees.front(), context);
} else {
for (const ManagedFnPtr& callee: callees){
processFnCallUncertain(callee, context);
}
}
}
break;
case Expression::IDENT:
assert(context.scope);
return processSymbol(expression.getValueString(), context);
default:
break;
}
return defaultValue<Output>();
}
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 std::string& ident, PassContext context);
}
#endif
diff --git a/cpp/src/pass/adhocpass.cpp b/cpp/src/pass/adhocpass.cpp
index 8473a79..ef9d1eb 100644
--- a/cpp/src/pass/adhocpass.cpp
+++ b/cpp/src/pass/adhocpass.cpp
@@ -1,81 +1,81 @@
/*
* adhoc.cpp
*
* Created on: Nov 28, 2015
* Author: pgess
*/
#include "pass/adhocpass.h"
#include "query/context.h"
namespace xreate {
AdhocScheme*
AdhocPass::determineForScope(CodeScope* entry){
const ScopePacked scopeId = man->clasp->pack(entry);
- const ContextDomain& domain = queryContext->getContext(scopeId);
+ const Domain& domain = queryContext->getContext(scopeId);
AdhocScheme* scheme = nullptr;
for (const Expression& context: domain){
if (context.__state != Expression::IDENT) continue;
if (__schemes.count(context.getValueString())){
assert(!scheme && "ambiguous context");
scheme = __schemes.at(context.getValueString());
}
}
assert(scheme && "Appropriate context not found");
return scheme;
}
const TypeAnnotation&
AdhocScheme::getResultType(){
return __resultType;
}
CodeScope*
AdhocScheme::getImplementationForCommand(const std::string& comm) {
assert(__commands.count(comm) && "Adhoc not defined");
return __commands.at(comm);
}
AdhocScheme::AdhocScheme(const Expression& scheme):
__resultType(scheme.type), __context(scheme.getValueString()) {
Expression cases = scheme.getOperands()[0];
for (const Expression& exprCase: cases.getOperands()){
CodeScope* blockComm = exprCase.blocks.front();
std::string nameCase = blockComm->__body.operands[0].getValueString();
CodeScope* blockImpl = *(++exprCase.blocks.begin());
__commands.emplace(nameCase, blockImpl);
}
}
const std::string&
AdhocScheme::getContext(){
return __context;
}
/*
void
AdhocPass::process(const Expression& expression, PassContext context, const std::string& varDecl=""){
if (expression == Exp)
}
*/
void
AdhocPass::run(){
queryContext = reinterpret_cast<ContextQuery*>(man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery));
auto range = man->root->__interfacesData.equal_range(ASTInterface::Adhoc);
for (auto i=range.first; i!= range.second; ++i){
AdhocScheme* scheme = new AdhocScheme(i->second);
__schemes.emplace(scheme->getContext(), scheme);
}
}
}
diff --git a/cpp/src/pass/cfgpass.cpp b/cpp/src/pass/cfapass.cpp
similarity index 53%
rename from cpp/src/pass/cfgpass.cpp
rename to cpp/src/pass/cfapass.cpp
index 120b80d..c4afd00 100644
--- a/cpp/src/pass/cfgpass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,98 +1,100 @@
-#include "cfgpass.h"
+#include "cfapass.h"
+#include "analysis/cfagraph.h"
+
#include <boost/range/iterator_range_core.hpp>
+
using namespace std;
using namespace xreate;
-
-
void
-CFGPass::initSignatures(){
+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 CFGPass::run(){
+void CFAPass::run(){
initSignatures();
return AbstractPass::run();
}
void
-CFGPass::finish()
+CFAPass::finish()
{
man->clasp->setCFAData(move(__context.graph));
return AbstractPass::finish();
}
void
-CFGPass::processFnCall(ManagedFnPtr function, PassContext context)
+CFAPass::processFnCall(ManagedFnPtr function, PassContext context)
{
ClaspLayer* clasp = man->clasp;
- __context.graph.addCallConnection(clasp->pack(context.scope), function->getName());
+ __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
-CFGPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){
+CFAPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){
ClaspLayer* clasp = man->clasp;
- __context.graph.addCallConnection(clasp->pack(context.scope), function->getName());
+ __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCallUncertain(function, context);
}
void
-CFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
+CFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
ClaspLayer* clasp = man->clasp;
CodeScope* scopeParent = context.scope;
ScopePacked scopeId = clasp->pack(scope);
if (scopeParent){
- __context.graph.addParentConnection(scopeId, clasp->pack(scopeParent));
+ __context.graph->addParentConnection(scopeId, clasp->pack(scopeParent));
} else {
- __context.graph.addParentConnection(scopeId, context.function->getName());
+ __context.graph->addParentConnection(scopeId, context.function->getName());
}
- //TEST scope annotations
+ //TOTEST scope annotations
//SECTIONTAG context gather scope annotations
- __context.graph.addScopeAnnotations(scopeId, scope->tags);
+ __context.graph->addScopeAnnotations(scopeId, scope->tags);
- __context.graph.addContextRules(scopeId, scope->contextRules);
+ __context.graph->addContextRules(scopeId, scope->contextRules);
return AbstractPass::process(scope, context, hintBlockDecl);
}
-//TEST scope annotations via scheme
+//TOTEST scope annotations via scheme
void
-CFGPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
+CFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
ClaspLayer* clasp = man->clasp;
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(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
+ __context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
-CFGPass::process(ManagedFnPtr function)
+CFAPass::process(ManagedFnPtr function)
{
- __context.graph.addFunctionAnnotations(function->getName(), function->getAnnotations());
+ __context.graph->addFunctionAnnotations(function->getName(), function->getTags());
return AbstractPass::process(function);
}
-CFGPass::CFGPass(PassManager* manager)
+CFAPass::CFAPass(PassManager* manager)
: AbstractPass(manager)
+ , __context{new xreate::analysis::CFAGraph(manager->clasp)}
{}
diff --git a/cpp/src/pass/cfgpass.h b/cpp/src/pass/cfapass.h
similarity index 77%
rename from cpp/src/pass/cfgpass.h
rename to cpp/src/pass/cfapass.h
index 8640f20..a064c6d 100644
--- a/cpp/src/pass/cfgpass.h
+++ b/cpp/src/pass/cfapass.h
@@ -1,34 +1,38 @@
// Control Flow Graph determination pass
#ifndef CFGPASS_H
#define CFGPASS_H
#include "passmanager.h"
#include "clasplayer.h"
#include "abstractpass.h"
+namespace xreate{namespace analysis {
+ class CFAGraph;
+}}
+
namespace xreate {
-class CFGPass : public AbstractPass<void>
+class CFAPass : public AbstractPass<void>
{
public:
- void process(ManagedFnPtr function) override;
+ void process(ManagedFnPtr function) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
void processFnCallUncertain(ManagedFnPtr function, 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;
- CFGPass(PassManager* manager);
+ CFAPass(PassManager* manager);
void finish() override;
void run() override;
private:
struct {
- CFAGraph graph;
+ xreate::analysis::CFAGraph* graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
}; }
#endif // CFGPASS_H
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 84e1cb5..6c52cee 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,654 +1,812 @@
#include "compilepass.h"
#include "clasplayer.h"
#include "llvmlayer.h"
#include <ast.h>
#include "query/containers.h"
#include "query/context.h"
-#include "compilation/instr-containers.h"
+#include "compilation/containers.h"
+#include "compilation/transformations.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
+//#include "compilation/targetinterpretation.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace xreate;
using namespace xreate::compilation;
using namespace llvm;
+//TODO use Scope<TargetLlvm>
+
//SECTIONTAG types/convert implementation
+//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/dissalow based on annotations)
+
+namespace xreate {
+
llvm::Value*
-doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, LLVMLayer* llvm){
- if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
- {
- llvm::IntegerType* tyTargetInt = llvm::dyn_cast<IntegerType>(tyTarget);
- llvm::IntegerType* tySourceInt = llvm::dyn_cast<IntegerType>(source->getType());
-
- if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
- return llvm->builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
- }
-
- if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
- return llvm->builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
- }
- }
+doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder){
+ if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
+ {
+ llvm::IntegerType* tyTargetInt = llvm::dyn_cast<IntegerType>(tyTarget);
+ llvm::IntegerType* tySourceInt = llvm::dyn_cast<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);
+ }
+ }
- return source;
+ if (source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()){
+ return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
+ }
+
+ return source;
}
CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
: scope(codeScope), pass(compilePass), function(f)
{}
-namespace xreate {
class CallStatement {
public:
virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>&) = 0;
};
class CallStatementRaw: public CallStatement{
public:
- CallStatementRaw(llvm::Value* callee): __callee(callee) {}
+ CallStatementRaw(llvm::Function* callee): __callee(callee) {}
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
+ auto argsFormal = __callee->args();
+
+ int pos=0;
+ //SECTIONTAG types/convert function ret value
+ for (auto argFormal = argsFormal.begin(); argFormal!=argsFormal.end(); ++argFormal, ++pos){
+ args[pos] = doAutomaticTypeConversion(args[pos], argFormal->getType(), builder);
+ }
+
return builder.CreateCall(__callee, args, hintDecl);
}
private:
- llvm::Value* __callee;
+ llvm::Function* __callee;
};
+//TASK implement inlining
class CallStatementInline: public CallStatement{
public:
CallStatementInline(FunctionUnit* caller, FunctionUnit* callee)
: __caller(caller), __callee(callee) {}
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
- //TEST inlining
- return __callee->compileInline(move(args), __caller);
+ //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();
}
private:
FunctionUnit* __caller;
FunctionUnit* __callee;
+
+ bool isInline(){
+ // Symbol ret = Symbol{0, function->__entry};
+ // bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
+ //TODO consider inlining
+ return false;
+ }
+};
+
+template<class Parent>
+class CallStatementLateContext: public CallStatement{
+ {
+ if (specializations.size()< 2){
+ return Parent...
+ }
+
+
+
+
+
+
+
+ }
+
};
}
+void
+CodeScopeUnit::overrideDeclaration(const Symbol binding, Expression&& declaration){
+ function->getScopeUnit(binding.scope)->__declarationsOverriden.emplace(binding.identifier, move(declaration));
+}
+
+class ScopeDecorator{
+
+};
+
//SECTIONTAG late-context find callee function
-//TEST static late context decisions
-//TEST dynamic late context decisions
+//TOTEST static late context decisions
+//TOTEST dynamic late context decisions
+
CallStatement*
CodeScopeUnit::findFunction(const std::string& calleeName){
- LLVMLayer* llvm = pass->man->llvm;
- ClaspLayer* clasp = pass->man->clasp;
+ LLVMLayer* llvm = pass->man->llvm;
+ ClaspLayer* clasp = pass->man->clasp;
- ContextQuery* queryContext = pass->queryContext;
+ ContextQuery* queryContext = pass->queryContext;
- const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
- //check external function
- if (!specializations.size()){
- llvm::Function* external = pass->man->llvm->layerExtern->lookupFunction(calleeName);
+ //if no specializations registered - check external function
+ if (specializations.size()==0){
+ llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
- return new CallStatementRaw(external);
- }
+ return new CallStatementRaw(external);
+ }
- //no decisions required
- if (specializations.size()==1){
- if (!specializations.front()->guardContext.isValid()) {
- return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile());
- }
- }
+ //no decisions required
+ if (specializations.size()==1){
+ if (!specializations.front()->guardContext.isValid()) {
+ return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile());
+ }
+ }
- //prepare specializations dictionary
- typedef ExpressionSerialization<>::Serializer Serializer;
- typedef ExpressionSerialization<>::Code Code;
+ //TODO move dictSpecialization over to a separate function in order to perform cache, etc.
+ //prepare specializations dictionary
+ std::map<Expression, ManagedFnPtr> dictSpecializations;
- auto adapter = [](const ManagedFnPtr& p){ return p->guardContext; };
- Serializer serializer(specializations, adapter);
+ boost::optional<ManagedFnPtr> variantDefault;
+ boost::optional<ManagedFnPtr> variant;
- std::map<Code, ManagedFnPtr> dictSpecializations;
- boost::optional<ManagedFnPtr> variantDefault;
- boost::optional<ManagedFnPtr> variant;
+ for(const ManagedFnPtr& f: specializations){
+ const Expression& guard = f->guardContext;
- for(const ManagedFnPtr& f: specializations){
- const Expression& guard = f->guardContext;
+ //default case:
+ if (!guard.isValid()){
+ variantDefault = f;
+ continue;
+ }
- //default case:
- if (!guard.isValid()){
- variantDefault = f;
- continue;
- }
+ assert(dictSpecializations.emplace(guard, f).second && "Found several identical specializations");
+ }
- assert(dictSpecializations.emplace(serializer.getId(guard), f).second && "Found several appropriate specializations");
- }
+ //check static context
+ ScopePacked scopeCaller = clasp->pack(this->scope);
+ const string atomSpecialization = "specialization";
+ const Expression topicSpecialization(Operator::CALL, {(Atom<Identifier_t>(string(atomSpecialization))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
- //check static context
- const ScopeContextDecisions& decisions = queryContext->getStaticDecisions(clasp->pack(this->scope));
- if (decisions.count(calleeName)){
- variant = dictSpecializations.at(serializer.getId(decisions.at(calleeName)));
- }
+ const Decisions& decisions = queryContext->getFinalDecisions(scopeCaller);
+ if (decisions.count(topicSpecialization)){
+ variant = dictSpecializations.at(decisions.at(topicSpecialization));
+ }
- size_t sizeDemand = this->function->contextCompiler.getFunctionDemandSize();
+ //TODO check only demand for this particular topic.
+ size_t sizeDemand = this->function->contextCompiler.getFunctionDemandSize();
- //decision made if static context found or no late context exists(and there is default variant)
- bool flagHasStaticDecision = variant || (variantDefault && !sizeDemand);
+ //decision made if static context found or no late context exists(and there is default variant)
+ bool flagHasStaticDecision = variant || (variantDefault && !sizeDemand);
- //if no late context exists
- if (flagHasStaticDecision) {
- FunctionUnit* calleeUnit = pass->getFunctionUnit(variant? *variant: *variantDefault);
+ //if no late context exists
+ if (flagHasStaticDecision) {
+ FunctionUnit* calleeUnit = pass->getFunctionUnit(variant? *variant: *variantDefault);
- //inlining possible based on static decision only
- if (calleeUnit->isInline()) {
- return new CallStatementInline(function, calleeUnit);
- }
+ //inlining possible based on static decision only
+ if (calleeUnit->isInline()) {
+ return new CallStatementInline(function, calleeUnit);
+ }
- return new CallStatementRaw(calleeUnit->compile());
- }
+ return new CallStatementRaw(calleeUnit->compile());
+ }
- //require default variant if no static decision made
- assert(variantDefault);
+ //require default variant if no static decision made
+ assert(variantDefault);
- llvm::Function* functionVariantDefault = this->pass->getFunctionUnit(*variantDefault)->compile();
- return new CallStatementRaw(this->function->contextCompiler.findFunction(calleeName, functionVariantDefault));
+ llvm::Function* functionVariantDefault = this->pass->getFunctionUnit(*variantDefault)->compile();
+ return new CallStatementRaw(this->function->contextCompiler.findFunction(calleeName, functionVariantDefault, scopeCaller));
}
void
-CodeScopeUnit::bindArg(llvm::Value* var, std::string&& name)
+CodeScopeUnit::bindArg(llvm::Value* value, std::string&& alias)
{
- assert(scope->__vartable.count(name));
- VID id = scope->__vartable.at(name);
- __rawVars[id] = var;
+ //reset cached compiled value if any
+ raw = nullptr;
+
+ //ensure existing of an alias
+ assert(scope->__identifiers.count(alias));
+
+ //memorize new value for an alias
+ VID id = scope->__identifiers.at(alias);
+ __rawVars[id] = value;
}
llvm::Value*
CodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
+
+ Context ctx{this, this->function, this->pass};
+
+// if (pass->targetInterpretation->isAcceptable(expr)){
+// return pass->targetInterpretation->compile(expr, ctx);
+// }
+
+ llvm::Value* result = processLowlevel(expr, hintVarDecl);
+
+ if (pass->transformations->isAcceptable(expr)){
+ return pass->transformations->transform(expr, result, ctx);
+ }
+
+ return result;
+}
+
+llvm::Value*
+CodeScopeUnit::processLowlevel(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;
- containers::Instructions instructions = containers::Instructions({function, this, pass});
+ xreate::compilation::Advanced instructions = xreate::compilation::Advanced({this, function, pass});
switch (expr.op) {
- case Operator::ADD:
- case Operator::SUB:
- case Operator::MUL:
- case Operator::DIV:
- case Operator::EQU:
- case Operator::LSS:
- case Operator::GTR:
+ case Operator::ADD: 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]);
//SECTIONTAG types/convert binary operation
- right = doAutomaticTypeConversion(right, left->getType(), &l);
+ right = doAutomaticTypeConversion(right, left->getType(), l.builder);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
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:
return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU:
- left->dump();
- right->dump();
- return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_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"));
+ 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);
std::string nameCallee = expr.getValueString();
unique_ptr<CallStatement> callee(findFunction(nameCallee));
//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);
}
);
ScopePacked outerScopeId = pass->man->clasp->pack(this->scope);
//SECTIONTAG late-context propagation arg
size_t calleeDemandSize = pass->queryContext->getFunctionDemand(nameCallee).size();
if (calleeDemandSize){
- llvm::Value* argLateContext = function->contextCompiler.compileArgument(nameCallee, outerScopeId);
+ llvm::Value* argLateContext = function->contextCompiler.compileContextArgument(nameCallee, outerScopeId);
args.push_back(argLateContext);
}
return (*callee)(move(args), DEFAULT("res_"+nameCallee), l.builder);
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOOP_CONTEXT:
{
return instructions.compileLoopContext(expr, DEFAULT("tmp_loop"));
}
case Operator::LOGIC_AND: {
assert(expr.operands.size() == 1);
return process (expr.operands[0]);
}
case Operator::LIST:
{
return instructions.compileConstantArray(expr, DEFAULT("tmp_list"));
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::LIST_NAMED:
{
typedef Expanded<TypeAnnotation> ExpandedType;
ExpandedType tyRaw = l.ast->expandType(expr.type);
const std::vector<string> fields = (tyRaw.get().__operator == TypeOperator::CUSTOM)?
l.layerExtern->getStructFields(l.layerExtern->lookupType(tyRaw.get().__valueCustom))
: tyRaw.get().fields;
std::map<std::string, size_t> indexFields;
for(size_t i=0, size = fields.size(); i<size; ++i){
indexFields.emplace(fields[i], i);
}
llvm::StructType* tyRecord = llvm::cast<llvm::StructType>(l.toLLVMType(tyRaw));
llvm::Value* record = llvm::UndefValue::get(tyRecord);
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 = 0;
//TODO Null ad hoc Llvm implementation
// if (operand.isNone()){
// llvm::Type* tyNullField = tyRecord->getElementType(fieldId);
// result = llvm::UndefValue::get(tyNullField);
//
// } else {
result = process(operand);
// }
assert (result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolid(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
+ case Operator::FOLD_INF:
+ {
+ return instructions.compileFoldInf(expr, DEFAULT("fold"));
+ };
+
case Operator::INDEX:
{
//TODO allow multiindex
assert(expr.operands.size()==1);
const std::string &ident = expr.getValueString();
Symbol s = scope->findSymbol(ident);
- const TypeAnnotation& t = s.scope->findDefinition(s);
+ const TypeAnnotation& t = CodeScope::findDeclaration(s).type;
const ExpandedType& t2 = pass->man->root->expandType(t);
switch (t2.get().__operator)
{
case TypeOperator::STRUCT: case TypeOperator::CUSTOM:
{
Expression idx = expr.operands.at(0);
assert(idx.__state == Expression::STRING);
std::string idxField = idx.getValueString();
llvm::Value* aggr = compileSymbol(s, ident);
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::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(s, indexes, DEFAULT(string("el_") + ident));
};
default:
assert(false);
}
};
//SECTIONTAG adhoc actual compilation
case Operator::ADHOC: {
assert(function->adhocImplementation && "Adhoc implementation not found");
string comm = expr.operands[0].getValueString();
CodeScope* scope = function->adhocImplementation->getImplementationForCommand(comm);
CodeScopeUnit* unitScope = function->getScopeUnit(scope);
return unitScope->compile();
};
case Operator::SEQUENCE: {
assert (expr.getOperands().size());
llvm::Value* result;
for(const Expression &op: expr.getOperands()){
result = process(op, "");
}
return result;
}
case Operator::NONE:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT: {
const std::string &ident = expr.getValueString();
Symbol s = scope->findSymbol(ident);
return compileSymbol(s, ident);
}
case Expression::NUMBER: {
int literal = expr.getValueDouble();
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
}
case Expression::STRING: {
return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
case Expression::VARIANT: {
const ExpandedType& typVariant = pass->man->root->expandType(expr.type);
llvm::Type* typRaw = l.toLLVMType(typVariant);
int value = expr.getValueDouble();
return llvm::ConstantInt::get(typRaw, value);
}
default: {
break;
}
};
break;
default: break;
}
assert(false);
return 0;
}
llvm::Value*
CodeScopeUnit::compile(const std::string& hintBlockDecl){
if (raw != nullptr) return raw;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
raw = process(scope->__body);
return raw;
}
llvm::Value*
CodeScopeUnit::compileSymbol(const Symbol& s, std::string hintRetVar)
{
CodeScope* scope = s.scope;
CodeScopeUnit* self = function->getScopeUnit(scope);
if (self->__rawVars.count(s.identifier)) {
return self->__rawVars[s.identifier];
}
- return self->__rawVars[s.identifier] = self->process(scope->findDeclaration(s), hintRetVar);
-}
+ //compilation transformations could override symbol declarations.
+ Expression declaration = CodeScope::findDeclaration(s);
+ if (!declaration.isDefined()){
+ if (self->__declarationsOverriden.count(s.identifier)){
+ declaration = self->__declarationsOverriden[s.identifier];
-bool
-FunctionUnit::isInline(){
- Symbol ret = Symbol{0, function->__entry};
- bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
+ } else {
+ assert(false); //in case of bindings there should be raws already.
+ }
+ }
- return flagOnTheFly;
+ return self->__rawVars[s.identifier] = self->process(declaration, hintRetVar);
}
+//SECTIONTAG late-context FunctionDecorator
+template<class Parent>
+class LateContextFunctionDecorator: public Parent{
+
+ LateContextFunctionDecorator(ManagedFnPtr f, CompilePass* p)
+ : Parent(f, p), contextCompiler(this, p)
+ {}
+
+ std::vector<llvm::Type*> prepareArguments(){
+ std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
+
+ size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
+ if (sizeLateContextDemand) {
+ llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
+
+ arguments.push_back(tyDemand);
+ }
+ return arguments;
+ }
+
+ void prepareBindings(){
+ if (sizeLateContextDemand){
+ fargsI->setName("latecontext");
+ contextCompiler.rawContextArgument = &*fargsI;
+ }
+ }
+
+protected:
+ LateContextCompiler2 contextCompiler;
+};
+
+//SECTIONTAG adhoc FunctionDecorator
+template<class Parent>
+class AdhocFunctionDecorator: public Parent{
+protected:
+ llvm::Type* prepareResult(){
+ if (! function->isPrefunction){
+ return Parent::prepareResult();
+ }
+
+ AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(pass->man->getPassById(PassId::AdhocPass));
+ adhocImplementation = adhocpass->determineForScope(entry);
+
+ return llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
+ }
+
+private:
+ AdhocScheme* adhocImplementation=nullptr; //SECTIONTAG adhoc prefunc scheme declaration
+};
+
+template<class Decorator>
+class BasicFunctionDecorator: public Decorator{
+protected:
+ std::string prepareName(){
+ string name = ast->getFunctionVariants(function->__name).size() > 1?
+ function->__name + std::to_string(function.id()) :
+ function->__name;
+
+ return name;
+ }
+
+ virtual std::vector<llvm::Type*> prepareArguments(){
+ std::vector<llvm::Type*> signature;
+ std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
+ [this, llvm, ast, entry](const std::string &arg)->llvm::Type* {
+ assert(entry->__identifiers.count(arg));
+ VID argid = entry->__identifiers.at(arg);
+ return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
+ });
+ return signature;
+ }
+
+ virtual llvm::Type* prepareResult(){
+ return llvm->toLLVMType(ast->expandType(entry->__declarations[0].type));
+ }
+
+ virtual void prepareBindings(){
+ CodeScope* entry = function->__entry;
+
+ CodeScopeUnit* entryCompilation = getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = raw->arg_begin();
+ for (std::string &arg : entry->__bindings) {
+ VID argid = entry->__identifiers[arg];
+
+ entryCompilation->__rawVars[argid] = &*fargsI;
+ fargsI->setName(arg);
+ ++fargsI;
+ }
+ }
+};
+
+typedef LateContextFunctionDecorator<
+ AdhocFunctionDecorator<
+ BasicFunctionDecorator<FunctionUnit>>> DefaultFunctionUnit;
+
llvm::Function*
FunctionUnit::compile(){
if (raw != nullptr) return raw;
- std::vector<llvm::Type *> types;
+
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
- CodeScope* entry = function->__entry;
+
AST* ast = pass->man->root;
- const string& functionName = ast->getFunctionVariants(function->__name).size() > 1? function->__name + std::to_string(function.id()) : function->__name;
-
- std::transform(entry->__args.begin(), entry->__args.end(), std::inserter(types, types.end()),
- [this, llvm, ast, entry](const std::string &arg)->llvm::Type* {
- assert(entry->__vartable.count(arg));
- VID argid = entry->__vartable.at(arg);
- assert(entry->__definitions.count(argid));
- return llvm->toLLVMType(ast->expandType(entry->__definitions.at(argid)));
- });
-
- //SECTIONTAG late-context signature type
- size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
- if (sizeLateContextDemand) {
- llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
- types.push_back(tyDemand);
- }
- //SECTIONTAG adhoc func signature determination
- llvm::Type* expectedResultType;
- if (function->isPrefunction){
- AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(pass->man->getPassById(PassId::AdhocPass));
- adhocImplementation = adhocpass->determineForScope(entry);
- expectedResultType = llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
- } else {
- expectedResultType = llvm->toLLVMType(ast->expandType(entry->__definitions[0]));
- }
+ string&& functionName = prepareName();
+ std::vector<llvm::Type*>&& types = prepareArguments();
+ llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
-
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
+ prepareBindings();
- CodeScopeUnit* entryCompilation = getScopeUnit(entry);
- llvm::Function::arg_iterator fargsI = raw->arg_begin();
- for (std::string &arg : entry->__args) {
- VID argid = entry->__vartable[arg];
-
- entryCompilation->__rawVars[argid] = fargsI;
- fargsI->setName(arg);
- ++fargsI;
- }
-
- if (sizeLateContextDemand){
- fargsI->setName("latecontext");
- contextCompiler.raw = fargsI;
- }
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result = entryCompilation->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
- builder.CreateRet(doAutomaticTypeConversion(result, expectedResultType, llvm));
+ builder.CreateRet(doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent){
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
-llvm::Value*
-FunctionUnit::compileInline(std::vector<llvm::Value *> &&args, FunctionUnit* outer){
- CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
- for(int i=0, size = args.size(); i<size; ++i) {
- entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__args.at(i)));
- }
-
-
- return entryCompilation->compile();
-}
-
CodeScopeUnit*
FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
scopes.emplace(scope, std::unique_ptr<CodeScopeUnit>(unit));
}
return scopes.at(scope).get();
}
CodeScopeUnit*
FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
CodeScopeUnit*
FunctionUnit::getScopeUnit(ManagedScpPtr scope){
return getScopeUnit(&*scope);
}
FunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function){
unsigned int id = function.id();
if (!functions.count(id)){
- FunctionUnit* unit = new FunctionUnit(function, this);
- functions.emplace(id, std::unique_ptr<FunctionUnit>(unit));
+ FunctionUnit* unit = new DefaultFunctionUnit(function, this);
+ functions.emplace(id, unit);
return unit;
}
return functions.at(id).get();
}
void
CompilePass::run(){
- queryContext = reinterpret_cast<ContextQuery*> (man->clasp->getQuery(QueryId::ContextQuery));
+ transformations = new Transformations(this);
+ transformations->registerTransformer(new TransformerSaturation(transformations));
+
+ //targetInterpretation = new TargetInterpretation(this->man->root);
+
+ queryContext = reinterpret_cast<ContextQuery*> (man->clasp->getQuery(QueryId::ContextQuery));
//Find out main function;
ClaspLayer::ModelFragment model = man->clasp->query(Config::get("function-entry"));
assert(model && "Error: No entry function found");
assert(model->first != model->second && "Error: Ambiguous entry function");
string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model->first->second));
FunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction(){
assert(entry);
return entry;
}
void
CompilePass::prepareQueries(ClaspLayer* clasp){
clasp->registerQuery(new containers::Query(), QueryId::ContainersQuery);
clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
}
//CODESCOPE COMPILATION PHASE
//FIND SYMBOL(compilation phase):
//if (!forceCompile)
//{
// return result;
//}
// //search in already compiled vars
//if (__rawVars.count(vId))
//{
// return result;
//}
//if (!__declarations.count(vId)) {
// //error: symbol is uncompiled scope arg
// assert(false);
//}
//const Expression& e = __declarations.at(vId);
//__rawVars[vId] = process(e, l, name);
//FIND FUNCTION
//llvm::Function*
//CompilePass::findFunction(const std::string& name){
// ManagedFnPtr calleeFunc = man->root->findFunction(name);
// assert(calleeFunc.isValid());
// return nullptr;
//}
diff --git a/cpp/src/pass/compilepass.h b/cpp/src/pass/compilepass.h
index 17b4bdf..54fb72d 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,101 +1,120 @@
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include <compilation/latecontextcompiler2.h>
#include "abstractpass.h"
#include "llvm/IR/Function.h"
namespace xreate {
class AdhocScheme;
class ClaspLayer;
class ContextQuery;
class CallStatement;
}
namespace xreate {
class CompilePass;
namespace compilation {
class CodeScopeUnit;
class FunctionUnit;
+class TargetInterpretation;
+
struct Context{
- FunctionUnit* function;
CodeScopeUnit* scope;
+ FunctionUnit* function;
CompilePass* pass;
};
class CodeScopeUnit {
public:
CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
- void bindArg(llvm::Value* var, std::string&& name);
+ void bindArg(llvm::Value* value, std::string&& alias);
+ void overrideDeclaration(const Symbol binding, Expression&& declaration);
std::map<VID,llvm::Value*> __rawVars;
void reset(){raw = nullptr;}
llvm::Value* compile(const std::string& hintBlockDecl="");
llvm::Value* compileSymbol(const Symbol& s, std::string hintRetVar="");
llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="");
+ llvm::Value* processLowlevel(const Expression& expr, const std::string& hintVarDecl="");
+
CodeScope* scope;
private:
CompilePass* pass;
llvm::Value* raw = nullptr;
FunctionUnit* function;
+ std::unordered_map<VID, Expression> __declarationsOverriden;
+
CallStatement* findFunction(const std::string& callee);
};
-class FunctionUnit{
+class IFunctionDecorator {
+protected:
+ virtual std::string prepareName() = 0;
+ virtual std::vector<llvm::Type*> prepareArguments() = 0;
+ virtual llvm::Type* prepareResult() = 0;
+ virtual void prepareBindings() = 0;
+ virtual ~IFunctionDecorator(){}
+};
+
+class FunctionUnit: public IFunctionDecorator{
public:
FunctionUnit(ManagedFnPtr f, CompilePass* p)
- : function(f), pass(p), contextCompiler(this, p) {}
-
- llvm::Value* compileInline(std::vector<llvm::Value*>&& args, FunctionUnit* outer);
- bool isInline();
- llvm::Function* compile();
-
- CodeScopeUnit* getEntry();
- CodeScopeUnit* getScopeUnit(CodeScope* scope);
- CodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
-
- ManagedFnPtr function;
- llvm::Function* raw = nullptr;
- AdhocScheme* adhocImplementation=nullptr; //SECTIONTAG adhoc prefunc scheme declaration
-
+ : function(f), pass(p) {}
+
+ llvm::Function* compile();
+
+ CodeScopeUnit* getEntry();
+ CodeScopeUnit* getScopeUnit(CodeScope* scope);
+ CodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
+
+ ManagedFnPtr function;
+ llvm::Function* raw = nullptr;
+
+protected:
+ std::string prepareName();
+ std::vector<llvm::Type*> prepareArguments();
+ llvm::Type* prepareResult();
+
private:
- CompilePass* pass;
- std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
-
-public:
- LateContextCompiler2 contextCompiler;
+ CompilePass* pass;
+ std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
};
+ class Transformations;
} // end of namespace `xreate::compilation`
class CompilePass : public AbstractPass<void> {
friend class LateContextCompiler;
friend class LateContextCompiler2;
friend class compilation::CodeScopeUnit;
friend class compilation::FunctionUnit;
public:
+ compilation::Transformations* transformations;
+
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
compilation::FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
void run() override;
llvm::Function* getEntryFunction();
static void prepareQueries(ClaspLayer* clasp);
-
private:
- std::map<unsigned int, std::unique_ptr<compilation::FunctionUnit>> functions;
+ std::map<unsigned int, compilation::FunctionUnit> functions;
llvm::Function* entry = 0;
ContextQuery* queryContext;
+ compilation::TargetInterpretation* targetInterpretation;
+
};
}
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
new file mode 100644
index 0000000..2939d08
--- /dev/null
+++ b/cpp/src/pass/dfapass.cpp
@@ -0,0 +1,256 @@
+#include "pass/dfapass.h"
+#include "analysis/dfagraph.h"
+
+#include "passmanager.h"
+#include "clasplayer.h"
+
+#include <boost/format.hpp>
+
+using namespace std;
+using namespace xreate::analysis;
+
+namespace xreate{
+
+DFAPass::DFAPass(PassManager* manager)
+ : AbstractPass(manager)
+ , __context{new xreate::analysis::DFAGraph(manager->clasp)}
+ , clasp(manager->clasp)
+{}
+
+SymbolNode
+DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
+ const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
+ const SymbolPacked& retFormal{0, clasp->pack(scope)};
+ __context.graph->addConnection(retFormal, retActual, DFGConnection::STRONG);
+
+ return retFormal;
+}
+
+SymbolNode
+DFAPass::process(const Expression& expression, PassContext context, const std::string& decl)
+{
+ ExpressionCache cache;
+
+ if (!decl.empty()){
+ cache.result = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
+
+ } else if (!expression.tags.empty()) {
+ cache.result = __context.graph->createAnonymousSymbol(clasp->pack(context.scope));
+
+ } else {
+ cache.result = SymbolTransient{{}, clasp->pack(context.scope)};
+ }
+
+ cache.operands.reserve(expression.getOperands().size());
+ for (const Expression &op: expression.getOperands()) {
+ cache.operands.push_back(process(op, context));
+ }
+
+ cache.blocks.reserve(expression.blocks.size());
+ for (CodeScope* scope: expression.blocks) {
+ cache.blocks.push_back(process(scope, context));
+ }
+
+ if (expression.__state != Expression::COMPOUND) {
+ processElementaryOp(expression, context, cache, decl);
+
+ } else {
+ processCompoundOp(expression, context, cache, decl);
+ }
+
+ applyDependencies(expression, context, cache, decl);
+ applyStaticAnnotations(expression, context, cache, decl);
+ applySignatureAnnotations(expression, context, cache, decl);
+ applyInPlaceAnnotations(expression, context, cache, decl);
+
+//TODO Null ad hoc DFG implementation
+// if (expression.isNone()){
+// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
+// }
+
+ //non initialized(SymbolInvalid) value
+
+ return cache.result;
+}
+
+
+void
+DFAPass::processElementaryOp(const Expression& expression, PassContext context, DFAPass::ExpressionCache& cache, const std::string& varDecl){
+ switch(expression.__state) {
+ case Expression::IDENT: {
+ std::string identifier = expression.getValueString();
+
+ SymbolNode nodeFrom = AbstractPass::process(expression, context, identifier);
+ if (SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result)){
+ __context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::STRONG);
+ }
+
+ break;
+ }
+
+ default: break;
+ }
+}
+
+void
+DFAPass::processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl){
+
+ switch(expression.op) {
+ //apply calling relation
+ case Operator::CALL: {
+ const string &nameCalleeFunction = expression.getValueString();
+
+ //TODO implement processFnCall/Uncertain
+ list<ManagedFnPtr> variantsCalleeFunction = man->root->getFunctionVariants(nameCalleeFunction);
+ if (variantsCalleeFunction.size()!=1) return;
+ ManagedFnPtr function= variantsCalleeFunction.front();
+
+ // set calling relations:
+ CodeScope *scopeRemote = function->getEntryScope();
+ std::vector<SymbolNode>::iterator nodeActual = cache.operands.begin();
+ for (const std::string &identFormal: scopeRemote->__bindings) {
+ const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
+ __context.graph->addConnection(clasp->pack(symbolFormal, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK);
+ ++nodeActual;
+ }
+
+ //TODO represent RET connection
+ break;
+ }
+
+ //apply PROTOTYPE relation
+ case Operator::MAP: {
+ SymbolNode nodeFrom= cache.operands.front();
+
+ SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
+ assert(nodeFromPacked);
+
+ SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result);
+ assert(nodeTo);
+
+ __context.graph->addConnection(*nodeTo, *nodeFromPacked, DFGConnection::PROTOTYPE);
+ break;
+ }
+
+ default: break;
+ }
+}
+
+void
+DFAPass::applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
+ for (SymbolNode &op: cache.operands) {
+ __context.graph->addDependencyConnection(cache.result, op);
+ }
+
+ for (SymbolNode &block: cache.blocks) {
+ __context.graph->addDependencyConnection(cache.result, block);
+ }
+
+ switch(expression.__state) {
+ case Expression::IDENT: {
+ const string& identName = expression.getValueString();
+
+ SymbolNode identSymbol = clasp->pack(context.scope->findSymbol(identName), context.function->getName() + ":" + identName);
+ __context.graph->addDependencyConnection(cache.result, identSymbol);
+ }
+
+ default: break;
+ }
+}
+
+void
+DFAPass::applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
+
+ switch(expression.__state) {
+ case Expression::NUMBER:
+ case Expression::STRING:
+ __context.graph->addAnnotation(cache.result, Expression(Atom<Identifier_t>("static")));
+ break;
+
+ default: break;
+ }
+}
+
+void
+DFAPass::applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
+ if (__signatures.count(expression.op)) {
+ const Expression &scheme = __signatures.at(expression.op);
+
+ //TODO add possibility to specifi signature for a particular function
+// if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
+// string caption = expression.getValueString();
+// operands.push_back(process(Expression(move(caption)), context, ""));
+// }
+
+ std::vector<SymbolNode>::iterator arg = cache.operands.begin();
+ std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
+
+ while (tag != scheme.getOperands().end()) {
+ if (tag->__state != Expression::INVALID) {
+ __context.graph->addAnnotation(*arg, Expression(*tag));
+ }
+
+ ++arg; ++tag;
+ }
+
+ //TODO represent RET connection
+// Expression retTag = *scheme.getOperands().begin();
+// if (retTag.__state != Expression::INVALID) {
+// __context.graph->addAnnotation(node, move(retTag));
+// }
+ }
+}
+
+void
+DFAPass::applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
+ // write down in-place expression tags:
+ for (pair<std::string, Expression> tag: expression.tags) {
+ __context.graph->addAnnotation(cache.result, Expression(tag.second));
+ }
+}
+
+void
+DFAPass::run()
+{
+ init();
+ return AbstractPass::run();
+}
+
+void
+DFAPass::init()
+{
+ for (const Expression& scheme: man->root->__dfadata)
+ {
+ __signatures.emplace(scheme.op, scheme);
+ }
+}
+
+void DFAPass::finish()
+{
+ man->clasp->setDFAData(move(__context.graph));
+}
+
+template<>
+SymbolNode defaultValue(){return SymbolInvalid();};
+
+}
+
+
+
+
+
+/*
+if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
+ std::vector<Tag> tags;
+ tags.reserve(symbT->tags.size());
+
+ const std::string stmntRetTag = Config::get("clasp.ret.tag");
+ std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
+ [&stmntRetTag](const Expression& e) {
+ Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
+ return Tag{e, TagModifier::NONE};
+ });
+
+ clasp->cfagraph->addFunctionAnnotations(function->getName(), tags);
+}
+*/
\ No newline at end of file
diff --git a/cpp/src/pass/dfapass.h b/cpp/src/pass/dfapass.h
new file mode 100644
index 0000000..cc26e8c
--- /dev/null
+++ b/cpp/src/pass/dfapass.h
@@ -0,0 +1,49 @@
+// Data Flow Graph determination pass
+
+#ifndef DFGPASS_H
+#define DFGPASS_H
+
+#include "abstractpass.h"
+#include "analysis/dfagraph.h"
+
+namespace xreate {
+
+class ClaspLayer;
+
+class DFAPass : public AbstractPass<xreate::analysis::SymbolNode> {
+public:
+ xreate::analysis::SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
+ xreate::analysis::SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
+
+ DFAPass(PassManager* manager);
+
+ void init();
+ void run();
+ void finish();
+
+private:
+ struct
+ {
+ xreate::analysis::DFAGraph* graph;
+ } __context;
+
+ struct ExpressionCache{
+ std::vector<xreate::analysis::SymbolNode> operands;
+ std::vector<xreate::analysis::SymbolNode> blocks;
+ xreate::analysis::SymbolNode result;
+ };
+
+ std::map<Operator, Expression> __signatures; //DFA data for particular operators
+ ClaspLayer* clasp;
+
+ void processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
+ void processElementaryOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
+
+ void applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
+ void applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
+ void applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
+ void applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
+};
+};
+
+#endif
diff --git a/cpp/src/pass/dfgpass.cpp b/cpp/src/pass/dfgpass.cpp
deleted file mode 100644
index da501ad..0000000
--- a/cpp/src/pass/dfgpass.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-#include "dfgpass.h"
-#include "passmanager.h"
-#include "clasplayer.h"
-#include <boost/format.hpp>
-using namespace std;
-
-namespace xreate{
-DFGPass::DFGPass(PassManager* manager)
- : AbstractPass(manager), clasp(man->clasp)
-{}
-
-SymbolNode
-DFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
- /*
- if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
- std::vector<Tag> tags;
- tags.reserve(symbT->tags.size());
-
- const std::string stmntRetTag = Config::get("clasp.ret.tag");
- std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
- [&stmntRetTag](const Expression& e) {
- Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
- return Tag{e, TagModifier::NONE};
- });
-
- clasp->cfagraph.addFunctionAnnotations(function->getName(), tags);
- }
- */
-
- const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
- const SymbolPacked& retFormal{0, clasp->pack(scope)};
- __context.graph.addConnection(retFormal, retActual, DFGConnection::ALIAS);
-
- return retFormal;
-}
-
-SymbolNode
-DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
-{
- // write down adhoc expression tags:
- if (expression.tags.size() && decl.length()) {
- for (pair<std::string, Expression> tag: expression.tags) {
- SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
- __context.graph.addAnnotation(nodeThis, Expression(tag.second));
- }
- }
-
- switch(expression.__state) {
- case Expression::IDENT: {
- const string& ident = expression.getValueString();
- SymbolNode nodeFrom = AbstractPass::process(expression, context, decl);
- SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident), context.function->getName() + ":" + ident);
-
- __context.graph.addConnection(nodeTo, nodeFrom, DFGConnection::ALIAS);
- return nodeTo;
- }
-
- default: break;
- }
-
-//TODO Null ad hoc DFG implementation
-// if (expression.isNone()){
-// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
-// }
-
- switch(expression.op) {
- case Operator::CALL: {
- const string &name = expression.getValueString();
-
- std::vector<SymbolNode> operands;
- operands.reserve(expression.getOperands().size());
-
- for (const Expression &op: expression.getOperands()) {
- operands.push_back(process(op, context));
- }
-
- //TODO implement processFnCall/Uncertain
- list<ManagedFnPtr> functions = man->root->getFunctionVariants(name);
- if (functions.size()!=1) return SymbolInvalid();
- ManagedFnPtr function= functions.front();
-
- // set calling relations:
- CodeScope *scopeRemote = function->getEntryScope();
- std::vector<SymbolNode>::iterator nodeActual = operands.begin();
- for (const std::string &identFormal: scopeRemote->__args) {
- const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
- __context.graph.addConnection(clasp->pack(symbolFormal, name + ":" + identFormal), *nodeActual, DFGConnection::OPT);
- ++nodeActual;
- }
-
- //TODO need SymbolTransient::connection mark in order to represent OPT connection
- return clasp->pack(Symbol{0, scopeRemote}, name + ": *retv");
- }
-
- default: break;
- }
-
-
-
- SymbolNode result = AbstractPass::process(expression, context, decl);
-
- if (expression.__state != Expression::COMPOUND){
- return result;
- }
-
- std::vector<SymbolNode> operands;
- if (__signatures.count(expression.op)) {
- const Expression &scheme = __signatures.at(expression.op);
-
- operands.reserve(expression.getOperands().size());
-
- if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
- string caption = expression.getValueString();
- operands.push_back(process(Expression(move(caption)), context, ""));
- }
-
- for (const Expression &op: expression.getOperands()) {
- operands.push_back(process(op, context));
- }
-
- std::vector<SymbolNode>::iterator arg = operands.begin();
- std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
-
- while (tag != scheme.getOperands().end()) {
- if (tag->__state != Expression::INVALID) {
- __context.graph.addAnnotation(*arg, Expression(*tag));
- }
-
- ++arg; ++tag;
- }
-
- Expression retTag = *scheme.getOperands().begin();
- if (retTag.__state != Expression::INVALID) {
- __context.graph.addAnnotation(result, move(retTag));
- }
- }
-
- // adhoc for MAP case, TODO reorganize code in more clear manner
- if (expression.op == Operator::MAP) {
- SymbolNode nodeFrom;
-
- if (operands.size()) {
- nodeFrom = operands.at(0);
- } else {
- nodeFrom = process(expression.getOperands().at(0), context);
- }
-
- assert(!decl.empty());
- SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
- SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
- assert(nodeFromPacked);
- __context.graph.addConnection(move(nodeTo), *nodeFromPacked, DFGConnection::PROTO);
- }
-
- return result;
-}
-
-void
-DFGPass::run()
-{
- init();
- return AbstractPass::run();
-}
-
-void
-DFGPass::init()
-{
- for (const Expression& scheme: man->root->__dfadata)
- {
- __signatures.emplace(scheme.op, scheme);
- }
-}
-
-void DFGPass::finish()
-{
- man->clasp->addDFAData(move(__context.graph));
-}
-
-template<>
-SymbolNode defaultValue(){return SymbolInvalid();};
-
-}
diff --git a/cpp/src/pass/dfgpass.h b/cpp/src/pass/dfgpass.h
deleted file mode 100644
index d29ecf3..0000000
--- a/cpp/src/pass/dfgpass.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Data Flow Graph determination pass
-
-#ifndef DFGPASS_H
-#define DFGPASS_H
-
-#include "abstractpass.h"
-#include "clasplayer.h"
-
-namespace xreate {
-
-class ClaspLayer;
-
-class DFGPass : public AbstractPass<SymbolNode> {
-public:
- SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="");
- SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
-
- DFGPass(PassManager* manager);
-
- void init();
- void run();
- void finish();
-private:
- struct
- {
- DFAGraph graph;
- } __context;
-
- std::map<Operator, Expression> __signatures; //DFA data for particular operators
- ClaspLayer* clasp;
-};
-};
-
-#endif
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
new file mode 100644
index 0000000..968efa4
--- /dev/null
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -0,0 +1,334 @@
+/*
+ * File: interpretationpass.cpp
+ * Author: pgess
+ *
+ * Created on July 5, 2016, 5:21 PM
+ */
+
+#include "pass/interpretationpass.h"
+#include "compilation/transformations.h"
+#include <compilation/targetinterpretation.h>
+#include "ast.h"
+//DEBT implement InterpretationPass purely in clasp
+//DEBT represent InterpretationPass as general type inference
+
+using namespace std;
+
+namespace xreate{
+
+enum InterpretationQuery{QUERY_INTR_ONLY, QUERY_CMPL_ONLY};
+
+template<>
+InterpretationResolution
+defaultValue<InterpretationResolution>(){
+ return CMPL_ONLY;
+}
+
+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== BOTH){
+ return unify(flagB, flags...);
+ }
+
+ if (flagB == BOTH) {
+ return unify(flagA, flags...);
+ }
+
+ assert(flagA == flagB);
+ return flagA;
+}
+
+namespace detail {
+ 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));
+ }
+}
+
+template<InterpretationQuery FLAG_REQUIRED>
+bool checkConstraints(std::vector<InterpretationResolution>&& flags) {
+ assert(flags.size());
+
+ InterpretationResolution flag = flags.front();
+ return detail::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 (detail::checkConstraints<FLAG_REQUIRED_A>(flag)){
+ return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
+ }
+
+ return false;
+}
+
+void
+setSpecializedOperator(const Expression& expression, const InterpretationOperator& op){
+ if (Attachments::exists<Expression, InterpretationData>(expression)){
+ InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression);
+ data.op = op;
+
+ } else {
+ Attachments::put<Expression, InterpretationData>(expression, {BOTH, op});
+ }
+
+ compilation::Transformations::subscribe<Expression, compilation::TargetInterpretation>(expression);
+}
+
+InterpretationResolution
+recognizeTags(const map<std::string, Expression>& tags){
+ auto i = tags.find("interpretation");
+ if (i== tags.end()){
+ return BOTH;
+ }
+
+ 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 == "force"){
+ return INTR_ONLY;
+
+ } else if (cmd == "suppress"){
+ return CMPL_ONLY;
+ }
+
+ return BOTH;
+}
+
+void
+recognizeTags(const Expression& e){
+ InterpretationData tag{recognizeTags(e.tags), NONE};
+ Attachments::put<Expression, InterpretationData>(e, tag);
+}
+
+InterpretationResolution
+recognizeTags(const ManagedFnPtr& f){
+ return recognizeTags(f->getTags());
+}
+
+InterpretationPass::InterpretationPass(PassManager* manager)
+ : AbstractPass(manager) {}
+
+InterpretationResolution
+InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl){
+ recognizeTags(expression);
+
+ InterpretationResolution resolution = BOTH;
+
+ switch (expression.__state){
+
+ case Expression::NUMBER:
+ case Expression::STRING: {
+ break;
+ }
+
+ case Expression::IDENT: {
+ resolution = Parent::processSymbol(expression.getValueString(), context);
+ break;
+ }
+
+ case Expression::COMPOUND:
+ break;
+
+ default: { resolution = INTR_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: {
+ //TODO cope with static/dynamic context
+
+ for (const Expression &op: expression.getOperands()) {
+ resolution = unify(resolution, process(op, context));
+ }
+
+ list<ManagedFnPtr> callees = man->root->getFunctionVariants(expression.getValueString());
+ if (callees.size()!=1){
+ resolution = CMPL_ONLY;
+ break;
+ }
+
+ ManagedFnPtr callee = callees.front();
+ const Symbol& symbCalleeFunc{0, callee->getEntryScope()};
+
+ //recursion-aware processing:
+ // - skip self recursion
+ const Symbol& symbSelfFunc{0, context.function->getEntryScope()};
+ if (symbSelfFunc == symbCalleeFunc){
+ break;
+ }
+
+ // - in order to recognize indirect recursion mark this function resolution as POSTPONED
+ auto& cache = getSymbolCache();
+ if (!cache.isCached(symbSelfFunc)){
+ cache.setCachedValue(symbSelfFunc, POSTPONED);
+ }
+
+ InterpretationResolution resCallee = process(callee);
+ if (resCallee == POSTPONED){
+ assert(false && "Indirect recursion detected: can't decide on interpretation resolution");
+ }
+
+ resolution = unify(resolution, resCallee);
+ 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})){
+ setSpecializedOperator(expression, IF_INTERPRET_CONDITION);
+ flagCondition = BOTH;
+ }
+
+ 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];
+ getSymbolCache().setCachedValue(scopeBody->findSymbol(nameEl), InterpretationResolution(flagInput));
+
+ const std::string& nameAccum = expression.bindings[1];
+ getSymbolCache().setCachedValue(scopeBody->findSymbol(nameAccum), InterpretationResolution(flagAccumInit));
+
+ InterpretationResolution flagBody = Parent::process(expression.blocks.front(), context);
+
+ //special case: FOLD_INTERPRET_INPUT
+ if (checkConstraints<QUERY_INTR_ONLY>({flagInput})){
+ setSpecializedOperator(expression, FOLD_INTERPRET_INPUT);
+ flagInput = BOTH;
+ }
+
+ resolution = unify(flagInput, flagAccumInit, flagBody);
+ break;
+ }
+
+ case Operator::INDEX: {
+ resolution = unify(
+ process(expression.operands[0], context),
+ Parent::processSymbol(expression.getValueString(), 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})){
+ setSpecializedOperator(expression, SWITCH_INTERPRET_CONDITION);
+ flagHeaders = BOTH;
+ }
+
+ //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::LIST:
+ case Operator::LIST_NAMED: {
+ for (const Expression &op: expression.getOperands()) {
+ resolution = unify(resolution, process(op, context));
+ }
+
+ break;
+ }
+
+ default: {
+ resolution = CMPL_ONLY;
+ Parent::process(expression, context, decl);
+ break;
+ }
+ }
+
+ InterpretationResolution resolutionExpected = Attachments::get<Expression, InterpretationData>(expression, {BOTH, NONE})
+ .resolution;
+
+ resolution = unify(resolution, resolutionExpected);
+ if (resolution == INTR_ONLY){
+ Attachments::put<Expression, InterpretationData>(expression, {INTR_ONLY, NONE});
+ compilation::Transformations::subscribe<Expression, compilation::TargetInterpretation>(expression);
+ }
+
+
+ return resolution;
+}
+
+ InterpretationResolution
+ InterpretationPass::process(ManagedFnPtr function){
+ InterpretationResolution resExpected = recognizeTags(function);
+
+ //mark preliminary function resolution same as expected
+ if (resExpected != BOTH){
+ const Symbol& symbSelfFunc{0, function->getEntryScope()};
+ getSymbolCache().setCachedValue(symbSelfFunc, move(resExpected));
+ }
+
+ CodeScope* entry = function->getEntryScope();
+ auto& cache = getSymbolCache();
+ std::vector<std::string> args = entry->__bindings;
+
+ for (int argNo = 0, size = args.size(); argNo< size; ++argNo){
+ Symbol symbArg = entry->findSymbol(args[argNo]);
+ InterpretationResolution resArg = recognizeTags(entry->findDeclaration(symbArg).tags);
+ cache.setCachedValue(symbArg, move(resArg));
+ }
+
+ InterpretationResolution resActual = Parent::process(function);
+ return unify(resActual, resExpected);
+ }
+}
+-
\ No newline at end of file
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
new file mode 100644
index 0000000..0992d6e
--- /dev/null
+++ b/cpp/src/pass/interpretationpass.h
@@ -0,0 +1,47 @@
+/*
+ * File: interpretationpass.h
+ * Author: pgess
+ *
+ * Created on July 5, 2016, 5:21 PM
+ */
+
+#ifndef INTERPRETATIONPASS_H
+#define INTERPRETATIONPASS_H
+
+#include "abstractpass.h"
+
+namespace xreate {
+
+ enum InterpretationResolution{BOTH, INTR_ONLY, CMPL_ONLY, POSTPONED};
+ enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION};
+
+ struct InterpretationData{
+ InterpretationResolution resolution;
+ InterpretationOperator op;
+ };
+
+ template<>
+ InterpretationResolution
+ defaultValue<InterpretationResolution>();
+
+ template<>
+ struct AttachmentsDict<InterpretationData>
+ {
+ typedef InterpretationData Data;
+ static const unsigned int key = 3;
+ };
+
+ 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);
+
+ InterpretationPass(PassManager* manager);
+ };
+}
+
+
+#endif /* INTERPRETATIONPASS_H */
+
diff --git a/cpp/src/pass/loggerpass.cpp b/cpp/src/pass/loggerpass.cpp
index ce8e552..f4471c8 100644
--- a/cpp/src/pass/loggerpass.cpp
+++ b/cpp/src/pass/loggerpass.cpp
@@ -1,106 +1,108 @@
/*
* logging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#include <pass/loggerpass.h>
-#include "compilation/instr-containers.h"
+#include "compilation/containers.h"
#include "utils.h"
using namespace std;
using namespace llvm;
namespace xreate {
void LoggerPass::init(ClaspLayer* clasp){
auto model = clasp->query(Config::get("logging.id"));
if(!model) return;
for (ClaspLayer::ModelIterator rec = model->first; rec!=model->second; ++rec){
std::tuple<SymbolPacked> _v =ClaspLayer::parse<SymbolPacked>(rec->second);
Symbol v = clasp->unpack(get<0>(_v));
- SymbolAttachments::put<IsLogging>(v, true);
+ Attachments::put<Symbol, IsLogging>(v, true);
}
}
void
LoggerPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (varDecl.size()){
Symbol v = context.scope->findSymbol(varDecl);
- if (SymbolAttachments::get<IsLogging>(v, false)){
+ if (Attachments::get<Symbol, IsLogging>(v, false)){
compilation::FunctionUnit* func = compiler->getFunctionUnit(context.function);
compilation::CodeScopeUnit* scope = func->getScopeUnit(context.scope);
- compilation::Context compilationContext{func, scope, compiler};
+ compilation::Context compilationContext{scope, func, compiler};
inject(v, compilationContext);
}
}
return AbstractPass<void>::process(expression, context, varDecl);
}
void LoggerPass::inject(const Symbol& symbol, const compilation::Context& context){
- llvm::Value* source = context.scope->compileSymbol(symbol);
- ExpandedType typSource = man->root->expandType(CodeScope::findDefinition(symbol));
- string format = "";
- switch (typSource->__value) {
- case TypePrimitive::Int : case TypePrimitive::Num : case TypePrimitive::I32: case TypePrimitive::I8:
- format = "%d\n";
- break;
-
- case TypePrimitive::String:
- format = "%s\n";
- break;
-
- default:
- assert(false && "No appropriate type for logging");
- }
-
- containers::Instructions compiler(context);
-
- LLVMLayer* llvm = context.pass->man->llvm;
- llvm->builder.SetInsertPoint(*source->use_begin());
- llvm::Value* formatRaw = compiler.compileConstantStringAsPChar(format, "logformat");
-
- llvm->builder.CreateCall2(refPrintf, formatRaw, source);
+ //TODO fix log injection
+
+// llvm::Value* source = context.scope->compileSymbol(symbol);
+// ExpandedType typSource = man->root->expandType(CodeScope::findDefinition(symbol).type);
+// string format = "";
+// switch (typSource->__value) {
+// case TypePrimitive::Int : case TypePrimitive::Num : case TypePrimitive::I32: case TypePrimitive::I8:
+// format = "%d\n";
+// break;
+//
+// case TypePrimitive::String:
+// format = "%s\n";
+// break;
+//
+// default:
+// assert(false && "No appropriate type for logging");
+// }
+//
+// xreate::compilation::Advanced instructions(context);
+//
+// LLVMLayer* llvm = context.pass->man->llvm;
+// llvm->builder.SetInsertPoint(llvm->builder.GetInsertBlock(), *source->use_begin());
+// llvm::Value* formatRaw = instructions.compileConstantStringAsPChar(format, "logformat");
+//
+// llvm->builder.CreateCall2(refPrintf, formatRaw, source);
}
void
LoggerPass::initOutput(){
LLVMLayer* llvm = man->llvm;
refPrintf = llvm->module->getFunction("printf");
if (!refPrintf) {
PointerType* typPtrI8 = PointerType::get(IntegerType::get(llvm->module->getContext(), 8), 0);
std::vector<Type*>argsPrintf{typPtrI8};
FunctionType* signaturePrintf = FunctionType::get(
/*Result=*/IntegerType::get(llvm->module->getContext(), 32),
/*Params=*/argsPrintf,
/*isVarArg=*/true);
refPrintf = llvm::Function::Create(
/*Type=*/signaturePrintf,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"printf", llvm->module); // (external, no body)
refPrintf->setCallingConv(CallingConv::C);
}
}
LoggerPass::LoggerPass(PassManager* manager)
: AbstractPass<void>(manager)
{
initOutput();
init(man->clasp);
}
void
LoggerPass::initDependencies(CompilePass* pass){
compiler = pass;
}
} /* namespace xreate */
diff --git a/cpp/src/pass/loggerpass.h b/cpp/src/pass/loggerpass.h
index 2c15b70..252e9c8 100644
--- a/cpp/src/pass/loggerpass.h
+++ b/cpp/src/pass/loggerpass.h
@@ -1,44 +1,44 @@
/*
* logging.h
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#ifndef SRC_LOGGING_H_
#define SRC_LOGGING_H_
#include "ast.h"
#include <llvm/IR/Value.h>
#include "pass/compilepass.h"
#include "pass/abstractpass.h"
#include "clasplayer.h"
namespace xreate {
class LoggerPass:public AbstractPass<void>, public IQuery {
public:
void inject(const Symbol& symbol, const compilation::Context& context);
LoggerPass(PassManager* manager);
virtual void init(ClaspLayer* clasp);
void initDependencies(CompilePass* pass);
virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
private:
CompilePass* compiler = nullptr;
llvm::Function* refPrintf;
void initOutput();
};
struct IsLogging{};
template<>
struct AttachmentsDict<IsLogging> {
typedef bool Data;
- static const unsigned int key = 5;
+ static const unsigned int key = 2;
};
} /* namespace xreate */
#endif /* SRC_LOGGING_H_ */
diff --git a/cpp/src/passmanager.cpp b/cpp/src/passmanager.cpp
index 5f2dac3..ccc9338 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager.cpp
@@ -1,112 +1,120 @@
#include <pass/abstractpass.h>
#include <pass/loggerpass.h>
#include "query/containers.h"
#include "passmanager.h"
#include "pass/compilepass.h"
#include "pass/adhocpass.h"
#include "Parser.h"
-#include "pass/cfgpass.h"
-#include "pass/dfgpass.h"
+#include "pass/cfapass.h"
+#include "pass/dfapass.h"
#include <list>
#include <stdio.h>
using namespace xreate;
using namespace std;
PassManager*
PassManager::prepareForCode(std::string&& code){
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
return prepareForCode(&scanner);
}
PassManager*
PassManager::prepareForCode(FILE* code){
Scanner scanner(code);
return prepareForCode(&scanner);
}
PassManager*
PassManager::prepareForCode(Scanner* code){
- Parser parser(code);
- parser.Parse();
- assert(!parser.errors->count && "Parser errors");
+ Parser parser(code);
+ parser.Parse();
+ assert(!parser.errors->count && "Parser errors");
- PassManager* man = new PassManager;
- AST* ast = new AST(parser.root);
+ PassManager* man = new PassManager;
+ AST* ast = new AST(parser.root);
- man->root = ast;
- man->clasp = new ClaspLayer();
+ man->root = ast;
+ man->clasp = new ClaspLayer();
- man->clasp->ast = man->root;
- man->llvm = new LLVMLayer(man->root);
+ man->clasp->ast = man->root;
+ man->llvm = new LLVMLayer(man->root);
- CFGPass* passCFG = new CFGPass(man);
-
- //TODO is it really DFGPass needs CFGpass?
- man->registerPass(new DFGPass(man), PassId::DFGPass, passCFG);
- man->registerPass(passCFG, PassId::CFGPass);
- man->registerPass(new AdhocPass(man), PassId::AdhocPass);
-
- CompilePass::prepareQueries(man->clasp);
-
- return man;
+ CompilePass::prepareQueries(man->clasp);
+ return man;
}
void
PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
{
- __passes.emplace(id, pass);
+ __passes.emplace(id, pass);
__passDependencies.emplace(parent, pass);
}
AbstractPassBase*
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<AbstractPassBase*> passes{nullptr};
+ while (passes.size()){
+ AbstractPassBase* parent = passes.front();
+
+ auto range = __passDependencies.equal_range(parent);
+
+ for (auto i=range.first; i!=range.second; ++i){
+ AbstractPassBase* pass = i->second;
+
+ pass->run();
+ pass->finish();
+
+ passes.push_back(pass);
+ }
+
+ passes.pop_front();
+ }
+}
+
void*
PassManager::run()
{
- runWithoutCompilation();
+ runWithoutCompilation();
CompilePass* compiler = new CompilePass(this);
compiler->run();
//Compiler Dependents:
LoggerPass* logger = new LoggerPass(this);
logger->initDependencies(compiler);
logger->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
void PassManager::runWithoutCompilation(){
- if (flagIsProcessed) return;
-
- std::list<AbstractPassBase*> passes{nullptr};
- while (passes.size()){
- AbstractPassBase* parent = passes.front();
-
- auto range = __passDependencies.equal_range(parent);
-
- for (auto i=range.first; i!=range.second; ++i){
- AbstractPassBase* pass = i->second;
-
- pass->run();
- pass->finish();
-
- passes.push_back(pass);
- }
-
- passes.pop_front();
- }
-
+ if (flagIsProcessed) return;
+
+ CFAPass* passCFG = new CFAPass(this);
+
+ //TODO is it really DFGPass needs CFGpass?
+ this->registerPass(new DFAPass(this), PassId::DFGPass, passCFG);
+ this->registerPass(passCFG, PassId::CFGPass);
+ this->registerPass(new AdhocPass(this), PassId::AdhocPass);
+
+ this->executePasses();
clasp->run();
flagIsProcessed = true;
}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index 86de4f3..cb55967 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,53 +1,56 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include <string>
#include <map>
//stdio external
struct _IO_FILE;
typedef struct _IO_FILE FILE;
class Scanner;
namespace xreate {
class AbstractPassBase;
class ClaspLayer;
class LLVMLayer;
class AST;
enum class PassId {
CFGPass,
CompilePass,
DFGPass,
EnvironmentTestsPass,
LoggerPass,
AdhocPass,
- RulesPass
+ RulesPass,
+ InterpretationPass
};
class PassManager
{
public:
~PassManager();
void*run();
void runWithoutCompilation();
+ void executePasses();
void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr);
AbstractPassBase* getPassById(const PassId& id);
+ bool isPassRegistered(const PassId& id);
static PassManager* prepareForCode(std::string&& code);
static PassManager* prepareForCode(FILE* code);
ClaspLayer* clasp;
LLVMLayer* llvm;
AST* root;
private:
//typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
//FILTERS_STORAGE __filters;
std::map<PassId, AbstractPassBase*> __passes;
std::multimap<AbstractPassBase*, AbstractPassBase*> __passDependencies;
bool flagIsProcessed = false;
static PassManager* prepareForCode(Scanner* code);
}; }
#endif
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 662f41e..8f37165 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,163 +1,164 @@
//
// Created by pgess on 3/14/15.
//
#include <clasplayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
+ typedef Attachments attach;
- typedef SymbolAttachments attach;
- if (attach::exists<Implementation>(s))
+ if (attach::exists<Symbol, Implementation>(s))
{
- return attach::get<Implementation>(s);
+ return attach::get<Symbol, Implementation>(s);
}
return Implementation::create(s);
}
void
Query::init(ClaspLayer* clasp)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//read all proto data
auto range = clasp->query(Config::get("containers.id.prototypes"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom) {
auto data = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0> (data));
Symbol prototype = clasp->unpack(get<1> (data));
prototypes[root] = prototype;
}
// fill implementation data for a data sources:
range = clasp->query(Config::get("containers.id.implementations"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto data = ClaspLayer::parse<SymbolPacked, string>(atom->second);
Symbol var = clasp->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
Implementation impl = Implementation::create(var);
- SymbolAttachments::put<Implementation>(var, move(impl));
+ Attachments::put<Symbol, Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
//fill implementation data for a cluster roots
for (const pair<Symbol, string> & root: roots)
{
Symbol prototype = prototypes[root.first];
while (prototypes.count(prototype)) {
prototype = prototypes.at(prototype);
}
- SymbolAttachments::put<Implementation>(root.first, Implementation(SymbolAttachments::get<Implementation>(prototype)));
+ Attachments::put<Symbol, Implementation>(root.first, Implementation(Attachments::get<Symbol, Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
range = clasp->query(Config::get("containers.id.clusters"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto info = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0>(info));
Symbol child = clasp->unpack(get<1>(info));
if (!(child == root)) {
- Implementation rootImpl = SymbolAttachments::get<Implementation>(root);
- SymbolAttachments::put<Implementation>(child, move(rootImpl));
+ Implementation rootImpl = Attachments::get<Symbol, Implementation>(root);
+ Attachments::put<Symbol, Implementation>(child, move(rootImpl));
}
}
flagIsDataLoaded = true;
}
//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
Implementation
Implementation::create(const Symbol &var)
{
+ //TODO review implementation determination strategy
Expression varDecl = CodeScope::findDeclaration(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;
+ default: break;
};
ImplementationLinkedList ill(var);
if (ill){
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
}
Implementation
Implementation::create(const Symbol& var, const std::string& implSerialized)
{
Expression varDecl = CodeScope::findDeclaration(var);
if (implSerialized == Config::get("containers.impl.solid"))
{
return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
} else if (implSerialized == Config::get("containers.impl.onthefly")) {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}};
}
assert(false && "unable to determine proper implementation for the symbol");
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source){
const Expression& sourceExpr = CodeScope::findDeclaration(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 663b08c..ec474d0 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,83 +1,83 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
- enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
+ 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;
const ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
~Query(){}
private:
bool flagIsDataLoaded = 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/context.cpp b/cpp/src/query/context.cpp
index 732ca16..efa6af1 100644
--- a/cpp/src/query/context.cpp
+++ b/cpp/src/query/context.cpp
@@ -1,167 +1,244 @@
/*
* adhoc.cpp
*
* Created on: Dec 1, 2015
* Author: pgess
*/
#include <query/context.h>
#include <boost/range/iterator_range_core.hpp>
#include <boost/iterator/transform_iterator.hpp>
using namespace std;
namespace xreate {
-ContextQuery::ContextQuery()
- : domainEmpty(vector<Expression>()) {}
+const Domain domainEmpty;
+const Decisions decisionsEmpty;
+const FunctionDemand functionDemandEmpty;
+
+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:
+ case Expression::VARIANT:
+ return a.getValueString() < b.getValueString();
+
+ case Expression::NUMBER:
+ return a.getValueDouble() < b.getValueDouble();
+
+ case Expression::COMPOUND: {
+ assert(a.op == Operator::CALL);
+ assert(a.blocks.size()==0);
+ assert(b.blocks.size()==0);
+
+ if (a.operands.size() != b.operands.size()){
+ return (a.operands.size() < b.operands.size());
+ }
+
+ if (a.getValueString() != b.getValueString()){
+ return a.getValueString() < b.getValueString();
+ }
+
+ 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;
+}
+
+ContextQuery::ContextQuery(){}
+
-const ContextDomain&
-ContextQuery::getContext(const ScopePacked& scopeId){
+const Domain&
+ContextQuery::getContext(const ScopePacked& scopeId) const{
if (!__modelContext.count(scopeId)){
return domainEmpty;
}
return __modelContext.at(scopeId);
}
-const ContextDomain&
-ContextQuery::getContext(CodeScope* const scope){
+const Domain&
+ContextQuery::getContext(CodeScope* const scope) const{
return getContext(clasp->pack(scope));
}
-
+//DEBT compatibility of forced context with context resolution for interpretation
void
ContextQuery::forceContext(const ScopePacked& scopeId, std::list<Expression> context){
// TODO remove forced context of the same class/type only, possibly
//remove any previous forced context for this scopeId
//__modelForcedContext.erase(scopeId);
//TASK restore forceContext
//std::multimap<ScopePacked, Expression> __modelForcedContext;
/*
std::transform(context.begin(), context.end(), inserter(__modelForcedContext, __modelForcedContext.end()),
[scopeId](const Expression& context){return make_pair(scopeId, context);});
*/
}
void
ContextQuery::init(ClaspLayer* clasp){
const std::string& atomEarlyBinding = Config::get("clasp.bindings.scope");
this->clasp = clasp;
ClaspLayer::ModelFragment query = clasp->query(atomEarlyBinding);
- //static context
+ //static context
if (query){
- map<ScopePacked, vector<Expression>> dictContext;
-
- for (auto i = query->first; i!=query->second; ++i){
- ScopePacked idScope;
- Expression context;
- tie(idScope, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
- dictContext[idScope].push_back(context);
- }
-
- for (map<ScopePacked, vector<Expression>>::value_type& entry: dictContext){
- __modelContext.insert(move(entry));
- }
+ map<ScopePacked, vector<Expression>> dictContext;
+
+ for (auto i = query->first; i!=query->second; ++i){
+ ScopePacked idScope;
+ Expression context;
+ tie(idScope, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
+ dictContext[idScope].push_back(context);
+ }
+
+ for (map<ScopePacked, vector<Expression>>::value_type& entry: dictContext){
+ __modelContext.insert(move(entry));
+ }
}
- //static decisions
- query = clasp->query(Config::get("clasp.bindings.scope_decision"));
- if (query){
- for (auto i = query->first; i!=query->second; ++i){
- ScopePacked scopeId;
- string function;
- Expression specialization;
- tie(scopeId, function, specialization) = ClaspLayer::parse<ScopePacked, string, Expression>(i->second);
- ScopeContextDecisions& scope = __modelStaticDecisions[scopeId];
- assert(scope.emplace(function, specialization).second && "Possibly more than one decision");
- }
- }
+ prepareFunctionDemandModel();
+ prepareDecisionModels();
+}
- //Fetch function specialization domains
- std::multimap<string, Expression> modelDomains;
- const list<ManagedFnPtr>& functions = clasp->ast->getAllFunctions();
- for (auto f: functions){
- if (f->guardContext.isValid()){
- modelDomains.emplace(f->getName(), f->guardContext);
- }
- }
- auto adapter = [](const std::pair<const string&,const Expression>& p){ return p.second; };
-
- auto iBegin = modelDomains.begin();
- while (iBegin!=modelDomains.end()){
- string function = iBegin->first;
- auto iEnd = modelDomains.upper_bound(function);
- auto iBeginAdapted = boost::make_transform_iterator(iBegin,adapter);
- auto iEndAdapted = boost::make_transform_iterator(iEnd,adapter);
- ContextDomain dom(iBeginAdapted, iEndAdapted);
- __modelFunctionDomain.emplace(function, move(dom));
- iBegin = iEnd;
- }
- prepareDemandModel();
-}
+void
+ContextQuery::prepareFunctionDemandModel(){
+ const std::string& atomFunctionDemand = Config::get("clasp.bindings.function_demand");
+
+ ClaspLayer::ModelFragment query = clasp->query(atomFunctionDemand);
+ if (query)
+ for (auto i = query->first; i!=query->second; ++i){
+ string function;
+ Expression topic;
+ tie(function, topic) = ClaspLayer::parse<string, Expression>(i->second);
-const ContextDomain&
-ContextQuery::getFunctionDomain(const std::string& name) const {
- if (__modelFunctionDomain.count(name)){
- return __modelFunctionDomain.at(name);
+ FunctionDemand& demand = __modelFunctionDemand[function];
+ demand.left.insert(make_pair(demand.left.size(), topic));
}
+}
+
+void
+ContextQuery::prepareDecisionModels(){
+ const std::string& atomDecision = Config::get("clasp.bindings.scope_decision");
+ const std::string& atomDependentDecision = Config::get("clasp.context.decisions.dependent");
- return domainEmpty;
+ std::multimap<Expression, Expression> modelDomains;
+
+
+ ClaspLayer::ModelFragment query = clasp->query(atomDecision);
+ if (query){
+ for (auto i = query->first; i!=query->second; ++i){
+ ScopePacked scopeId;
+ Expression topic;
+ Expression decision;
+
+ std::tie(scopeId, topic, decision) = ClaspLayer::parse<ScopePacked, Expression, Expression>(i->second);
+
+ if (decision.getValueString() == atomDependentDecision) {
+ assert(decision.operands.size() == 2);
+
+ const Expression& decisionGuard = decision.operands[1];
+ const Expression& decisionValue = decision.operands[0];
+
+ __modelDependentDecisions[scopeId][topic].emplace(decisionGuard, decisionValue);
+ modelDomains.emplace(topic, decisionValue);
+
+ } else {
+ Decisions& decisionsOfScope = __modelStaticDecisions[scopeId];
+ assert(decisionsOfScope.emplace(topic, decision).second && "Possibly more than one decision");
+ modelDomains.emplace(topic, decision);
+ }
+ }
+ }
+
+
+ //populate topic domains:
+ auto adapter = [](const std::pair<const Expression&,const Expression>& p){ return p.second; };
+
+ auto iBegin = modelDomains.begin();
+ while (iBegin!=modelDomains.end()){
+ const Expression topic = iBegin->first;
+ auto iEnd = modelDomains.upper_bound(topic);
+ auto iBeginAdapted = boost::make_transform_iterator(iBegin,adapter);
+ auto iEndAdapted = boost::make_transform_iterator(iEnd,adapter);
+ Domain dom(iBeginAdapted, iEndAdapted);
+ __modelTopicDomains.emplace(topic, move(dom));
+ iBegin = iEnd;
+ }
}
-const FunctionContextDemand&
+const FunctionDemand&
ContextQuery::getFunctionDemand(const std::string& name) const {
if (__modelFunctionDemand.count(name)){
return __modelFunctionDemand.at(name);
}
- return decisionsEmpty;
+ return functionDemandEmpty;
}
-const ScopeContextDecisions&
-ContextQuery::getStaticDecisions(const ScopePacked& scopeId){
+const Decisions&
+ContextQuery::getFinalDecisions(const ScopePacked& scopeId) const{
if (__modelStaticDecisions.count(scopeId)){
- return __modelStaticDecisions[scopeId];
+ return __modelStaticDecisions.at(scopeId);
}
- return contextDecisionsEmpty;
+ return decisionsEmpty;
+}
+
+const Domain&
+ContextQuery::getTopicDomain(const Expression& topic) const{
+ if (__modelTopicDomains.count(topic)){
+ return __modelTopicDomains.at(topic);
+ }
+
+ return domainEmpty;
}
-void
-ContextQuery::prepareDemandModel(){
- const std::string& atomFunctionDemand = Config::get("clasp.bindings.function_demand");
+const DependentDecision&
+ContextQuery::getDependentDecision(ScopePacked scope, const Expression& topic) const{
+ auto itDecisionsAllTopics = __modelDependentDecisions.find(scope);
+ if (itDecisionsAllTopics != __modelDependentDecisions.end()){
+ auto itDecisions = itDecisionsAllTopics->second.find(topic);
- ClaspLayer::ModelFragment query = clasp->query(atomFunctionDemand);
- if (query)
- for (auto i = query->first; i!=query->second; ++i){
- string function;
- string decision;
- tie(function, decision) = ClaspLayer::parse<string, string>(i->second);
+ if (itDecisions != itDecisionsAllTopics->second.end()){
+ return itDecisions->second;
+ }
+ }
- FunctionContextDemand& decisions = __modelFunctionDemand[function];
- decisions.left.insert(make_pair(decisions.size(), decision));
- }
+ return decisionsEmpty;
}
// const std::string& atomLateBinding = Config::get("clasp.bindings.function_uncertain");
// query = clasp->query(atomLateBinding);
//
// std::map<std::string, std::vector<Expression>> dictFunctionDomain;
// if (query){
// for (auto i = query->first; i!=query->second; ++i){
// string nameFunction;
// Expression context;
// tie(nameFunction, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
// dictFunctionDomain.at(nameFunction).push_back(context);
// }
//
// for(auto& entry: dictFunctionDomain){
// __modelFunctionDomain.emplace(entry.first, move(entry.second));
// }
// }
} /* namespace xreate */
diff --git a/cpp/src/query/context.h b/cpp/src/query/context.h
index 7117ac0..b32a021 100644
--- a/cpp/src/query/context.h
+++ b/cpp/src/query/context.h
@@ -1,89 +1,97 @@
/*
* adhoc.h
*
* Created on: Dec 1, 2015
* Author: pgess
*/
#ifndef SRC_QUERY_CONTEXT_H_
#define SRC_QUERY_CONTEXT_H_
#include "clasplayer.h"
#include "ast.h"
#include "serialization.h"
#include <unordered_map>
#include <boost/bimap.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/member.hpp>
+
namespace xreate {
-typedef ExpressionSerialization<RequirementIntegralCode>::Serializer ContextDomain;
-typedef boost::bimap<size_t, std::string> FunctionContextDemand;
-typedef std::map<std::string, Expression> ScopeContextDecisions;
+typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
+typedef boost::bimap<size_t, Expression> FunctionDemand;
+typedef std::map<Expression, Expression> Decisions;
+typedef std::map<Expression, Expression> DependentDecision;
class ContextQuery: public IQuery {
-public:
//AdhocQuery();
- const ContextDomain& getContext(const ScopePacked& scopeId);
- const ContextDomain& getContext(CodeScope* const scope);
+public:
+ const Domain& getContext(const ScopePacked& scopeId) const;
+ const Domain& getContext(CodeScope* const scope) const;
void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
- const ContextDomain& getFunctionDomain(const std::string& name) const;
- const FunctionContextDemand& getFunctionDemand(const std::string& name) const;
- const ScopeContextDecisions& getStaticDecisions(const ScopePacked& scopeId);
+ const Domain& getTopicDomain(const Expression& topic) const;
+ const DependentDecision& getDependentDecision(ScopePacked scope, const Expression& topic) const;
+ const FunctionDemand& getFunctionDemand(const std::string& name) const;
+ const Decisions& getFinalDecisions(const ScopePacked& scopeId) const;
+
virtual void init(ClaspLayer* clasp);
ContextQuery();
virtual ~ContextQuery(){};
private:
ClaspLayer* clasp;
- std::map<ScopePacked, ContextDomain> __modelContext;
- std::map<std::string, ContextDomain> __modelFunctionDomain;
- std::map<std::string, FunctionContextDemand> __modelFunctionDemand;
- std::map<ScopePacked, ScopeContextDecisions> __modelStaticDecisions;
-
- const ContextDomain domainEmpty;
- const FunctionContextDemand decisionsEmpty;
- const ScopeContextDecisions contextDecisionsEmpty;
-
- void prepareDemandModel();
+ std::map<ScopePacked, Domain> __modelContext;
+ std::map<std::string, FunctionDemand> __modelFunctionDemand;
+ std::map<ScopePacked, Decisions> __modelStaticDecisions;
+ std::map<Expression, Domain> __modelTopicDomains;
+ std::map<ScopePacked, std::map<Expression, DependentDecision>> __modelDependentDecisions;
+
+ void prepareFunctionDemandModel();
+ void prepareDecisionModels();
};
+bool operator < (const Expression&, const Expression&);
+
} /* namespace xreate */
/*
template <typename ATTACHMENTS>
class ContextAttachments: private std::unordered_map<size_t, ATTACHMENTS> {
typedef std::unordered_map<size_t, ATTACHMENTS> PARENT;
public:
ContextAttachments(ContextAttachments&& other)
: PARENT(std::move(other)), domain(std::move(other.domain)) {}
ContextAttachments(std::vector<Expression>&& expressions, std::vector<ATTACHMENTS>&& attachments)
: domain(move(expressions))
{
size_t size = domain.size();
for (size_t i=0; i<size; ++i){
PARENT::emplace(i, std::move(attachments[i]));
}
}
size_t size() const {
return PARENT::size();
}
size_t count(const Expression& e) const {
return (domain.getExpressionId(e)? 1: 0);
}
const ATTACHMENTS& at(const Expression& e) const{
auto id = domain.getExpressionId(e);
assert(id);
return PARENT::at(*id);
}
private:
ContextDomain domain;
};
typedef ContextAttachments<ManagedFnPtr> FunctionSpecializations ;
*/
#endif /* SRC_QUERY_CONTEXT_H_ */
diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/serialization/expressionserializer.cpp
index af7e8f1..42b5a15 100644
--- a/cpp/src/serialization/expressionserializer.cpp
+++ b/cpp/src/serialization/expressionserializer.cpp
@@ -1,287 +1,303 @@
/*
* expressionserializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
#include "serialization/expressionserializer.h"
-#include <boost/multiprecision/cpp_int.hpp>
-#include <boost/bimap.hpp>
-#include <boost/bimap/multiset_of.hpp>
-#include <boost/bimap/unordered_set_of.hpp>
+#include <cmath>
using namespace std;
-using namespace boost::bimaps;
+//using namespace boost::bimaps;
namespace xreate {
struct Index {
- string name;
- size_t degree; //count of parameters
- unsigned char level; //level in expression tree (depth of tree layer)
-
- bool operator< (const Index other) const{
- if (name != other.name) return name < other.name;
- if (degree != other.degree) return degree < other.degree;
- if (name != other.name) return level < other.level;
- return false;
- }
+ string name;
+ size_t degree; //count of parameters
+ unsigned char level; //level in expression tree (depth of tree layer)
+
+ bool operator< (const Index other) const{
+ if (name != other.name) return name < other.name;
+ if (degree != other.degree) return degree < other.degree;
+ if (name != other.name) return level < other.level;
+ return false;
+ }
};
class ExpressionSerializerPrivate {
//boost::bimap<Index, multiset_of<size_t>> __registry;
- struct {
- map<Index,size_t> left;
- } __registry;
- map<unsigned char, size_t> __range;
+ struct {
+ map<Index,size_t> left;
+ } __registry;
+ map<unsigned char, size_t> __range;
public:
- void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){
- if (!target) return;
- switch (e.op){
- case Operator::NONE: {
- switch (e.__state) {
- case Expression::STRING:
- case Expression::IDENT: {
- Index index{e.getValueString(), 0, level};
- if (!__registry.left.count(index)){
- target = boost::none;
- return;
- }
-
- size_t id = __registry.left.at(index);
- size_t range = __range[level];
- (*target) << make_pair(id, range);
- return;
- }
- default: break;
- }
- break;
- }
-
- case Operator::CALL: {
- Index index{e.getValueString(), e.operands.size(), level};
- if(!__registry.left.count(index)){
- target = boost::none;
- return;
- }
-
- size_t id = __registry.left.at(index);
- size_t range = __range[level];
- (*target) << make_pair(id, range);
-
- for (const Expression& operand: e.operands){
- pack(operand, level+1, target);
- }
- return;
- }
- default: break;
- }
-
- assert(false && "Expression too complicate for serialization");
- }
-
- void registerExpression(const Expression&e, unsigned char level){
- switch (e.op){
- case Operator::CALL: {
- Index index{e.getValueString(), e.operands.size(), level};
- if (__registry.left.insert(make_pair(index, __range[level])).second){
- __range[level]++;
- }
-
- for (const Expression& operand: e.operands){
- registerExpression(operand, level+1);
- }
- return;
- }
-
- case Operator::NONE: {
- switch (e.__state) {
- case Expression::STRING:
- case Expression::IDENT: {
- Index index{e.getValueString(), 0, level};
- if (__registry.left.insert(make_pair(index, __range[level])).second){
- __range[level]++;
- }
- return;
- }
- default: break;
- }
- break;
- }
-
- default: break;
- }
-
- assert(false && "Expression too complicate for serialization");
- }
+ void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){
+ if (!target) return;
+ switch (e.op){
+ case Operator::NONE: {
+ switch (e.__state) {
+ case Expression::NUMBER:
+ case Expression::STRING:
+ case Expression::IDENT : {
+
+ Index index;
+ if ((e.__state == Expression::NUMBER))
+ index = {std::to_string(e.getValueDouble()), 0, level};
+ else index = {e.getValueString(), 0, level};
+
+ if (!__registry.left.count(index)){
+ target = boost::none;
+ return;
+ }
+
+ size_t id = __registry.left.at(index);
+ size_t range = __range[level];
+ (*target) << make_pair(id, range);
+ return;
+ }
+ default: break;
+ }
+ break;
+ }
+
+ case Operator::CALL: {
+ Index index{e.getValueString(), e.operands.size(), level};
+ if(!__registry.left.count(index)){
+ target = boost::none;
+ return;
+ }
+
+ size_t id = __registry.left.at(index);
+ size_t range = __range[level];
+ (*target) << make_pair(id, range);
+
+ for (const Expression& operand: e.operands){
+ pack(operand, level+1, target);
+ }
+ return;
+ }
+ default: break;
+ }
+
+ assert(false && "Expression too complicate for serialization");
+ }
+
+ void registerExpression(const Expression&e, unsigned char level){
+ switch (e.op){
+ case Operator::CALL: {
+ Index index{e.getValueString(), e.operands.size(), level};
+ if (__registry.left.insert(make_pair(index, __range[level])).second){
+ __range[level]++;
+ }
+
+ for (const Expression& operand: e.operands){
+ registerExpression(operand, level+1);
+ }
+ return;
+ }
+
+ case Operator::NONE: {
+ Index index;
+
+ switch (e.__state) {
+ case Expression::STRING:
+ case Expression::IDENT: {
+ index = {e.getValueString(), 0, level};
+ if (__registry.left.insert(make_pair(index, __range[level])).second){
+ __range[level]++;
+ }
+ return;
+ }
+
+ case Expression::NUMBER: {
+ index = {std::to_string(e.getValueDouble()), 0, level};
+ if (__registry.left.insert(make_pair(index, __range[level])).second){
+ __range[level]++;
+ }
+ return;
+ }
+
+ default: break;
+ }
+ break;
+ }
+
+ default: break;
+ }
+
+ assert(false && "Expression too complicate for serialization");
+ }
};
ExpressionSerializer::ExpressionSerializer()
: strategy(new ExpressionSerializerPrivate()){
}
ExpressionSerializer::~ExpressionSerializer() {
delete strategy;
}
void
ExpressionSerializer::registerExpression(const Expression&e){
if (e.isValid())
strategy->registerExpression(e, 0);
}
PackedExpression
ExpressionSerializer::getId(const Expression& e){
OptionalPackedExpression result(move(PackedExpression()));
strategy->pack(e, 0, result);
assert(result);
return move(*result);
}
OptionalPackedExpression
ExpressionSerializer::getIdOptional(const Expression& e) const{
OptionalPackedExpression result(move(PackedExpression()));
strategy->pack(e, 0, result);
return result;
}
+ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){}
+
ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector<Expression>&& expressions)
: std::vector<Expression>(move(expressions)), serializer(*this){
size_t id =0;
for (const Expression& e: expressions){
__registry.emplace(serializer.getId(e), id++);
}
}
size_t
ExpressionSerializerIntegral::size() const{
return PARENT::size();
}
size_t
ExpressionSerializerIntegral::count(const Expression& e) const {
return (getIdOptional(e)? 1: 0);
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::begin() const {
return PARENT::begin();
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::end() const {
return PARENT::end();
}
size_t
ExpressionSerializerIntegral::getId(const Expression& e) const{
const auto& exprPacked = serializer.getIdOptional(e);
assert(exprPacked);
return __registry.at(*exprPacked);
}
boost::optional<size_t>
ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{
const auto& exprPacked = serializer.getIdOptional(e);
if (!exprPacked){
return boost::none;
}
return __registry.at(*exprPacked);
}
const Expression&
ExpressionSerializerIntegral::get(size_t id) const{
return at(id);
}
void
PackedExpression::operator<< (const std::pair<size_t, size_t>& value){
static const size_t sizeSizeT = sizeof(size_t);
const size_t& id = value.first;
const size_t& range = value.second;
int countSufficientBits = range <=1? 0 : ceil(log2(range));
if (0 < countRemainedBits && countRemainedBits < countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id >> (countSufficientBits - countRemainedBits);
countSufficientBits-=countRemainedBits;
countRemainedBits = 0;
}
if (countRemainedBits == 0) {
if (countSufficientBits == 0) return;
char* __storageNew = new char[size+sizeSizeT];
std::memcpy (__storageNew, __storage, size);
std::memset(__storageNew + size, 0, sizeSizeT);
delete[] __storage;
__storage = __storageNew;
size += sizeSizeT;
countRemainedBits = 8 * sizeSizeT;
}
if (countRemainedBits >= countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id << (countRemainedBits - countSufficientBits);
countRemainedBits -= countSufficientBits;
return;
}
assert("Unreachable block");
}
PackedExpression::PackedExpression(PackedExpression&& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
other.__storage = nullptr;
}
bool
PackedExpression::operator==(const PackedExpression& other) const{
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) == 0 ;
}
return false;
}
bool
PackedExpression::operator<(const PackedExpression& other) const{
if (size < other.size) { return true; }
if (countRemainedBits < other.countRemainedBits) return true;
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) < 0 ;
}
return false;
}
bool
PackedExpression::operator!=(const PackedExpression& other) const{
return ! ((*this) == other);
}
PackedExpression::~PackedExpression() {
delete[] __storage;
}
//PackedExpression::PackedExpression (const PackedExpression& other)
// : size(other.size), countRemainedBits(other.countRemainedBits)
//{
// __storage = new char[size];
// std::memcpy (__storage, other.__storage, size);
//}
} /* namespace xreate */
diff --git a/cpp/src/serialization/expressionserializer.h b/cpp/src/serialization/expressionserializer.h
index b4b2354..9acf8c4 100644
--- a/cpp/src/serialization/expressionserializer.h
+++ b/cpp/src/serialization/expressionserializer.h
@@ -1,100 +1,103 @@
/*
* expressionserializer.h
*
* Created on: Jan 4, 2016
* Author: pgess
*/
#ifndef SRC_EXPRESSIONSERIALIZER_H_
#define SRC_EXPRESSIONSERIALIZER_H_
#include "ast.h"
#include <string>
#include <boost/optional.hpp>
namespace xreate {
struct PackedExpression{
PackedExpression(){};
PackedExpression(PackedExpression&& other);
~PackedExpression();
void operator<< (const std::pair<size_t, size_t>& value);
char* operator*(){return __storage;}
bool operator==(const PackedExpression& other) const;
bool operator!=(const PackedExpression& other) const;
bool operator<(const PackedExpression& other) const;
private:
PackedExpression (const PackedExpression&)=delete;
PackedExpression& operator=(const PackedExpression&)=delete;
PackedExpression& operator=(PackedExpression&&)=delete;
char* __storage = nullptr;
size_t size =0;
unsigned char countRemainedBits =0;
};
typedef boost::optional<PackedExpression> OptionalPackedExpression;
class ExpressionSerializerPrivate;
class ExpressionSerializer {
public:
template<class Container>
ExpressionSerializer(const Container& source): ExpressionSerializer(){
for (const Expression& e: source) {
registerExpression(e);
}
}
template<class Container, class Transformer>
ExpressionSerializer(const Container& source, Transformer op): ExpressionSerializer(){
for (const typename Container::value_type& e: source) {
registerExpression(op(e));
}
}
ExpressionSerializer(ExpressionSerializer&& other)
: strategy(other.strategy) {other.strategy = 0; }
virtual ~ExpressionSerializer();
PackedExpression getId(const Expression& e);
OptionalPackedExpression getIdOptional(const Expression& e) const;
private:
ExpressionSerializerPrivate* strategy;
void registerExpression(const Expression&e);
ExpressionSerializer();
};
class ExpressionSerializerIntegral: private std::vector<Expression>{
typedef std::vector<Expression> PARENT;
public:
+ ExpressionSerializerIntegral();
ExpressionSerializerIntegral(const std::vector<Expression>&& expressions);
+
template<class Iterator>
ExpressionSerializerIntegral(Iterator first, Iterator last)
: ExpressionSerializerIntegral(std::vector<Expression>(first, last)){}
ExpressionSerializerIntegral(ExpressionSerializerIntegral&& other)
: PARENT(std::move(other)), __registry(std::move(other.__registry)), serializer(std::move(other.serializer)){}
+
size_t getId(const Expression& e) const;
boost::optional<size_t> getIdOptional(const Expression& e) const;
const Expression& get(size_t id) const;
size_t size() const;
size_t count(const Expression& e) const;
ExpressionSerializerIntegral::const_iterator begin() const;
ExpressionSerializerIntegral::const_iterator end() const;
private:
ExpressionSerializerIntegral(const ExpressionSerializerIntegral&)=delete;
std::map<PackedExpression, size_t> __registry;
ExpressionSerializer serializer;
};
} /* namespace xreate */
#endif /* SRC_EXPRESSIONSERIALIZER_H_ */
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index 2778ad0..a2f9b28 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,134 +1,134 @@
#ifndef UTILS_H
#define UTILS_H
#include "jeayeson/jeayeson.hpp"
-//TODO mark dirty members
+//TODO use type mark to mark dirty/mutable members
/*
template<class T>
struct DdesctructableClass<T> {
}
*/
/*
template<class OriginalType>
struct TagUpdatable{
TagUpdatable(const OriginalType& source)
: __source(source)
{}
TagUpdatable() = delete;
const OriginalType& __source;
};
struct Updatable;
template <class Tag, class OT>
struct TagsDictionary
{};
template<class OT>
struct TagsDictionary<Updatable, OT>
{
typedef TagUpdatable<OT> TagName;
};
template<class Tag, class OT>
struct awareOf
{
awareOf(OT& dest)
: __dest(dest)
{}
awareOf<Tag, OT>&
operator= (const typename TagsDictionary<Tag, OT>::TagName& source)
{
__dest = source.__source;
}
private:
OT& __dest;
};
template<class Tag<OT>>
const OT&
awareOf(const Tag<OT>& holder)
{
return std::forward<OT>(holder.__source);
}
*/
namespace xreate {
template<class Tag, class Source>
struct AddTag {
explicit
AddTag(const Source &src)
: __src(src) { }
explicit
AddTag(Source &&src)
: __src(std::move(src)) { }
operator const Source&() const{
return __src;
}
const Source& get() const{
return __src;
}
const Source*
operator->() const {
return &__src;
}
private:
Source __src;
};
struct Expand_t{};
template<class Source>
using Expanded = AddTag<Expand_t, Source>;
//DEBT move to resources compiler. https://github.com/markusfisch/cpprc
class Config {
private:
json_map __storage;
static Config __self;
Config();
public:
static std::string get(std::string key) {
return __self.__storage.get_for_path<json_value>(key).get<std::string>();
}
};
}
#define RST "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
#define FRED(x) KRED << x << RST
#define FGRN(x) KGRN <<x << RST
#define FYEL(x) KYEL << x << RST
#define FBLU(x) KBLU << x << RST
#define FMAG(x) KMAG x RST
#define FCYN(x) KCYN x RST
#define FWHT(x) KWHT x RST
#define BOLD(x) "\x1B[1m" x RST
#define UNDL(x) "\x1B[4m" x RST
#endif // UTILS_H
diff --git a/cpp/tests/CFGtests.cpp b/cpp/tests/CFGtests.cpp
index cbda26a..e9b7e0c 100644
--- a/cpp/tests/CFGtests.cpp
+++ b/cpp/tests/CFGtests.cpp
@@ -1,62 +1,109 @@
/*
* testsCFG.cpp
*
* Created on: Jul 17, 2015
* Author: pgess
*/
#include "passmanager.h"
-#include "pass/dfgpass.h"
+#include "pass/dfapass.h"
+#include "pass/cfapass.h"
+
+#include "analysis/DominatorsTreeAnalysisProvider.h"
+
#include "gtest/gtest.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/smart_ptr/scoped_array.hpp>
+
using namespace xreate;
using namespace std;
TEST(CFG, testFunctionAnnotationsClasp){
string&& program =
- "f2 = function()::int; annotationF2 {\n"
+ "f2 = function::int; annotationF2 {\n"
" 0\n"
"}\n"
"\n"
- "f1 = function():: int; entry; annotationF1 {\n"
+ "f1 = function:: int; entry; annotationF1 {\n"
" f2() + 10\n"
"}";
PassManager* man = PassManager::prepareForCode(move(program));
man->runWithoutCompilation();
ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1");
int countNoneValue = 0;
if (answer)
countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
answer = man->clasp->query("annotationF2");
countNoneValue = 0;
if (answer)
countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
}
TEST(CFG, testLoopContextExists){
PassManager* man = PassManager::prepareForCode (
"interface(cfa){\n"
" operator fold:: annotation1.\n"
"}\n"
"\n"
- "main = function() :: int; entry {\n"
+ "main = function:: int; entry {\n"
" x = [1..10]:: [int].\n"
- " sum = loop fold (x->el:: int, 0->sum:: int):: [int] {\n"
+ " sum = loop fold (x->el:: int, 0->sum):: int {\n"
" el + sum + f1()\n"
" }. \n"
" sum\n"
"}"
- "f1 = function()::int {\n"
+ "f1 = function::int {\n"
" x = 0:: int. "
" x\n"
"}"
);
man->runWithoutCompilation();
}
+
+TEST(CFG, CFGRoots){
+ std::string program =
+R"CODE(
+ main = function::int{a()+ b()}
+ a= function::int {c1() + c2()}
+ b= function::int {c2()}
+ c1=function::int{0}
+ c2=function::int{0}
+)CODE";
+
+ boost::scoped_ptr<PassManager> manager
+ (PassManager::prepareForCode(move(program)));
+
+ manager->registerPass(new CFAPass(manager.get()) , PassId::CFGPass);
+ manager->executePasses();
+ manager->clasp->run();
+
+ DominatorsTreeAnalysisProvider domProvider;
+ domProvider.run(manager->clasp);
+
+ DominatorsTreeAnalysisProvider::Dominators expectedFDom= {
+ {0, {0, 9}}
+ ,{1, {1, 4}}
+ ,{2, {7, 8}}
+ ,{3, {2, 3}}
+ ,{4, {5, 6}}
+ };
+
+ DominatorsTreeAnalysisProvider::Dominators expectedPostDom= {
+ {0, {5, 6}}
+ ,{1, {3, 4}}
+ ,{2, {8, 9}}
+ ,{3, {1, 2}}
+ ,{4, {7, 10}}
+ };
+
+ ASSERT_EQ(expectedFDom, domProvider.getForwardDominators());
+ ASSERT_EQ(expectedPostDom, domProvider.getPostDominators());
+}
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index c729026..e980a74 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,19 +1,18 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate-tests)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES($<TARGET_PROPERTY:xreate,INCLUDE_DIRECTORIES>)
-
# TESTS
#=========================
aux_source_directory(. TEST_FILES)
add_executable(${PROJECT_NAME} ${TEST_FILES})
target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/cpp/tests/DFGtests.cpp b/cpp/tests/DFGtests.cpp
index 7371367..088bc40 100644
--- a/cpp/tests/DFGtests.cpp
+++ b/cpp/tests/DFGtests.cpp
@@ -1,42 +1,42 @@
/*
* DFGtests.cpp
*
* Created on: Jul 23, 2015
* Author: pgess
*/
#include "passmanager.h"
-#include "pass/dfgpass.h"
+#include "pass/dfapass.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
TEST(DFG, testFunctionRetSymbolExists){
PassManager* man = PassManager::prepareForCode
("test = function():: int; entry {\n"
" data = [1..5]::[int].\n"
" \n"
" result = loop fold(data->i::int, 0->sum::int)::int{\n"
" if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
" }.\n"
" \n"
" result\n"
"}");
man->runWithoutCompilation();
ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.ret.symbol"));
if (answer)
EXPECT_EQ(1, std::distance(answer->first, answer->second));
for (auto functionIt = answer->first; functionIt != answer->second; ++functionIt){
- auto ret = ClaspLayer::parse<string, Gringo::Value>(functionIt->second);
+ auto ret = ClaspLayer::parse<string, Gringo::Symbol>(functionIt->second);
ASSERT_EQ("test", std::get<0>(ret));
SymbolPacked symbolRet = std::get<0>(ClaspLayer::parse<SymbolPacked>(std::get<1>(ret)));
ASSERT_EQ(3, symbolRet.identifier);
ASSERT_EQ(0, symbolRet.scope);
}
}
diff --git a/cpp/tests/adhoc-skipdetection.cpp b/cpp/tests/adhoc-skipdetection.cpp
index c1ba1a2..603891c 100644
--- a/cpp/tests/adhoc-skipdetection.cpp
+++ b/cpp/tests/adhoc-skipdetection.cpp
@@ -1,32 +1,34 @@
/*
* skipdetection.cpp
*
* Created on: Jul 10, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "clasplayer.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
-TEST(SkipDetection, testNoneValueTagExists){
+
+//TASK implement loop "skip" command
+TEST(Adhoc_Loop_SkipDetection, testNoneValueTagExists){
PassManager* man = PassManager::prepareForCode
("test = function():: int; entry {\n"
" data = [1..5]::[int].\n"
" \n"
" result = loop fold(data->i::int, 0->sum::int)::int{\n"
" if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
" }.\n"
" \n"
" result\n"
"}");
man->runWithoutCompilation();
ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.nonevalue"));
int countNoneValue = 0;
if (answer)
countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
}
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index 7c4de20..4868d3a 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,49 +1,49 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(AST, Containers1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
const AST& ast = parser.root;
fclose(input);
}
TEST(AST, InterfacesDataCFA) {
PassManager* man = PassManager::prepareForCode
("interface(cfa){\n"
" operator map :: annotation1.\n"
"}");
auto answer = man->root->__interfacesData.equal_range(CFA);
EXPECT_EQ(1, std::distance(answer.first, answer.second));
Expression&& scheme = move(answer.first->second);
EXPECT_EQ(Operator::MAP, scheme.op);
EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString());
}
TEST(AST, DISABLED_InterfacesDataDFA){
}
TEST(AST, DISABLED_InterfacesDataExtern){
}
-
+//TODO xreate.atg: replace all Type<> as ExprAnnotations<>
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index 97e4087..58cb59d 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,62 +1,62 @@
#include "passmanager.h"
#include "gtest/gtest.h"
using namespace xreate;
-//TEST FunctionUnit::compileInline
+//TOTEST FunctionUnit::compileInline
TEST(Compilation, DISABLED_functionInline1){
}
//DEBT implement no pkgconfig ways to link libs
TEST(Compilation, Sequence1){
PassManager* man = PassManager::prepareForCode(
"interface(extern-c){\n"
" libFake = library:: pkgconfig(\"libxml-2.0\").\n"
" \n"
" include {\n"
" libFake = [\"stdio.h\", \"stdlib.h\"]\n"
" }.\n"
"}"
"main = function:: int; entry {\n"
" sequence ["
" printf(\"FIRST-\"),\n"
" printf(\">SECOND\")\n"
" ]"
"}"
);
int (*main)() = (int (*)()) man->run();
testing::internal::CaptureStdout();
main();
std::string output = testing::internal::GetCapturedStdout();
ASSERT_STREQ("FIRST->SECOND", output.c_str());
}
TEST(Compilation, full_IFStatementWithVariantType){
PassManager* man = PassManager::prepareForCode(
"COLORS = type variant (RED, BLUE, GREEN).\n"
"\n"
" main = function(x::int):: int; entry {\n"
" color = if (x == 0 )::COLORS {RED} else {BLUE}.\n"
" if (color == BLUE)::int {1} else {0}\n"
" }"
);
int (*main)(int) = (int (*)(int)) man->run();
ASSERT_EQ(0, main(0));
ASSERT_EQ(1, main(1));
}
// "main = function:: int; entry {\n"
// " context:: expectNoErrors. "
// " buf1 = \"aaaaa\"::string.\n"
// " buf2 = \"aaaaa\"::string.\n"
// " sequence ["
// " sprintf(buf1, \"%d\", exec(\"bazaar --version\")),"
// " sprintf(buf2, \"%d\", exec(\"svn --version\")),"
// " printf(buf1),\n"
// " printf(buf2)\n"
// "]"
// "}"
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
index 56655b3..4c05c02 100644
--- a/cpp/tests/context.cpp
+++ b/cpp/tests/context.cpp
@@ -1,325 +1,370 @@
/*
* frame-context.cpp
*
* Created on: Dec 3, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "query/context.h"
#include "gtest/gtest.h"
#include <iostream>
#include <boost/scoped_ptr.hpp>
using namespace xreate;
//TEST(Context, frame_Context1){
// PassManager* man = PassManager::prepareForCode(
// " import raw (\"core/control-context.lp\")\n"
// " testC = function::int {\n"
// " context:: testC.\n"
//
// " 0\n"
// " }\n"
//
// " testA = function:: int {\n"
// " context:: testA; test.\n"
//
// " testC()\n"
// " }\n"
//
// " testB = function:: int {\n"
// " context:: testB; test.\n"
//
// " testC()\n"
// " }\n"
// );
//
// ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
// man->runWithoutCompilation();
//
// CodeScope* scopeTestC = man->root->findFunction("testC")->getEntryScope();
// const ContextDomain& context = query->getContext(man->clasp->pack(scopeTestC));
//
// int contextSize = context.size();
// EXPECT_EQ(2, contextSize);
//}
//
//TEST(Context, full_ContextBasedFunctionSpecialization){
//
// PassManager* man = PassManager::prepareForCode(
// " case context::toMillimeters {\n"
// " convert = function(source:: num)::num {\n"
// " 10 * source \n"
// " }\n"
// " }\n"
//
// " case context::toInches {\n"
// " convert = function(source:: num)::num {\n"
// " 2 * source \n"
// " }\n"
// " }\n"
//
// "test = function(vrnt:: int)::int; entry {\n"
// " switch(vrnt):: int\n"
// " case 0 {\n"
// " context:: toMillimeters.\n"
// " convert(1)\n"
// " }\n"
// "\n"
// " case 1 {\n"
// " context:: toInches.\n"
// " convert(1)\n"
// " }\n"
// " case default {0}\n"
// " }" );
//
// int (*main)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(10, main(0));
// ASSERT_EQ(2, main(1));
//}
//
//TEST(Context, full_LoopContext){
//
// PassManager* man = PassManager::prepareForCode("case context:: a {\n"
// " print = function:: string {\n"
// " \"a\"\n"
// " }}\n"
// "\n"
// " case context:: b {\n"
// " print = function:: string {\n"
// " \"b\"\n"
// " }}\n"
// "\n"
// " case context:: c {\n"
// " print = function:: string {\n"
// " \"c\"\n"
// " }}\n"
// "\n"
// " case context:: d {\n"
// " print = function:: string {\n"
// " \"d\"\n"
// " }}\n"
// "\n"
// " start = function(command::int)::string; entry {\n"
// " switch (command) :: string \n"
// " case 0 {\n"
// " context:: print(a); print(b); print(d).\n"
// "\n"
// " loop context (\"print\") {\n"
// " print()\n"
// " }\n"
// " }\n"
// "\n"
// " case default {\n"
// " context:: print(c).\n"
// " loop context (\"print\") {\n"
// " print()\n"
// " }\n"
// " }\n"
// " }");
//
//
// char* (*main)(int) =(char* (*)(int)) man->run();
// ASSERT_STREQ("c", main(1));
// ASSERT_STREQ("a", main(0));
//}
//
//TEST(Context, full_RuleContext){
// /*
// "rule context:: childs(Child)\n"
// " case artefact(Item)\n"
// " {\n"
// " artefact_depends(Item, Child)\n"
// " }";
// */
//
// PassManager* man = PassManager::prepareForCode(
// " case context:: toMilli {\n"
// " convert = function(length::int)::int{\n"
// " 10 * length\n"
// " }\n"
// " }\n"
// "\n"
// " case context:: toCenti {\n"
// " convert = function(length::int)::int{\n"
// " length\n"
// " }\n"
// " }\n"
// "\n"
// " main=function::int; entry {\n"
// " context:: output(milli).\n"
// "\n"
// " rule context::toMilli\n"
// " case output(milli) {true}\n"
// "\n"
// " convert(1)\n"
// " }" );
// man->clasp->addRawScript("true.");
//
// int (*entry)() = (int (*)()) man->run();
// ASSERT_EQ(10, entry());
//}
//
//TEST(Context, full_InheritedRuleContext){
// PassManager* man = PassManager::prepareForCode(
// " import raw (\"core/control-context.lp\") \n"
//
// " case context:: toMilli {\n"
// " convert = function(length::int)::int{\n"
// " 10 * length\n"
// " }\n"
// " }\n"
//
// " case context:: toCenti {\n"
// " convert = function(length::int)::int{\ n"
// " length\n"
// " }\n"
// " }\n"
// "\n"
//
// "main = function(comm:: num)::num; entry{\n"
// " rule context::X case output(X) {true}\n"
// "\n"
// " switch (comm)::num \n"
// " case 0 {\n"
// " context:: output(toMilli).\n"
// " convert(1)\n"
// " }\n"
// " case default {\n"
// " context:: output(toCenti).\n"
// " convert(1)\n"
// " }\n"
// " }");
//
// man->clasp->addRawScript("true.");
// int (*entry)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(10, entry(0));
// ASSERT_EQ(1, entry(1));
//}
//
//
//
//TEST(Context, full_LateContext){
// PassManager* man = PassManager::prepareForCode(
// "import raw (\"core/control-context.lp\")\n"
//
// " convert = function(length:: num)::num{\n"
// " 0\n"
// " }\n"
//
// "case context:: milli {\n"
// " convert = function(length:: num)::num{\n"
// " 1000 * length\n"
// " }\n"
// "}\n"
// "\n"
// "case context:: centi {\n"
// " convert = function(length:: num)::num{\n"
// " 100 * length\n"
// " }\n"
// "}\n"
// "\n"
// "calculate = function(length:: num)::num {\n"
// " convert(length)\n"
// "}\n"
// "\n"
// "main = function(com:: num):: num; entry {\n"
// " switch (com):: num \n"
// " case 0 {\n"
// " context:: milli.\n"
// " calculate(1)\n"
// " }\n"
// "\n"
// " case default{\n"
// " context:: centi. \n"
// " calculate(1)\n"
// " }\n"
// "}");
//
// man->runWithoutCompilation();
// ContextQuery* queryContext = reinterpret_cast<ContextQuery*>(man->clasp->getQuery(QueryId::ContextQuery));
// Expression exprSwitch = man->root->findFunction("main")->__entry->__body;
// CodeScope* blockDefault = man->root->findFunction("main")->__entry->__body.operands[1].blocks.front();
// ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
// const ContextDomain& domDefault = queryContext->getContext(blockDefaultId);
// ASSERT_EQ(1, domDefault.count(Expression(Atom<Identifier_t>("centi"))));
//
// std::list<ManagedFnPtr> variants = man->root->getFunctionVariants("convert");
// for (ManagedFnPtr f: variants){
// const Expression guard = f->guardContext;
// bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid());
// ASSERT_TRUE(result);
// }
//
// const FunctionContextDemand& demMain = queryContext->getFunctionDemand("main");
// ASSERT_EQ(0, demMain.size());
//
// const FunctionContextDemand& demCalculate = queryContext->getFunctionDemand("calculate");
// ASSERT_EQ(1, demCalculate.size());
// ASSERT_EQ(1, demCalculate.right.count("convert"));
//
// int (*entry)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(1000, entry(0));
// ASSERT_EQ(100, entry(1));
//}
TEST(Context, pathDependent_context){
std::string program =
-R"CODE(case context:: convert(milli, meters) {
+R"CODE(
+import raw("core/control-context.lp")
+
+convert = function(length:: num) :: num {
+ 0
+}
+
+case context:: convert(milli, meters) {
convert = function(length:: num) :: num {
1000 * length
}
}
case context:: convert(centi, meters) {
convert = function(length:: num) :: num {
100 * length
}
}
case context:: convert(centi, kilo) {
convert = function(length:: num) :: num {
100000 * length
}
}
case context:: convert(milli, kilo) {
convert = function(length:: num) :: num {
1000000 * length
}
}
+
+main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{
+ switch (unitsInput)::num
+ case 0 {
+ test_fromMilli(value, unitsOutput)
+ }
+ case 1 {
+ test_fromCenti(value, unitsOutput)
+ }
-test1_fromCentiToKilo = function(a::num)::num {
- context:: input(centi).
-
- toKilo(a)
+ case default {0}
}
-
-
-test2_fromMilliToMeters = function(a::num)::num{
+test_fromCenti = function(value::num, output::num)::num{
+ context:: input(centi).
+
+ switch(output):: num
+ case 0 {
+ toMeters(value)
+ }
+
+ case 1 {
+ toKilo(value)
+ }
+
+ case default {0}
+}
+
+test_fromMilli = function(value::num, output::num)::num{
context:: input(milli).
-
- toMeters(a)
+
+ switch(output):: num
+ case 0 {
+ toMeters(value)
+ }
+
+ case 1 {
+ toKilo(value)
+ }
+
+ case default {0}
}
-toMeters = function(a::num)::num {
- rule context :: convert(X, meters) case input(X) {true}
+toMeters = function(value::num)::num {
+ rule context:: convert(X, meters) case input(X) {true}
- convert(a)
+ doConvert(value)
}
-toKilo = function(a::num)::num {
- rule context :: convert(X, kilo) case input(X) {true}
+toKilo = function(value::num)::num {
+ rule context:: convert(X, kilo) case input(X) {true}
- convert(a)
+ doConvert(value)
+}
+
+doConvert = function(value::num)::num{
+ convert(value)
})CODE";
-
-
boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
man->runWithoutCompilation();
-}
+
+ int (*test)(int, int, int) = (int (*)(int, int, int))man->run();
+
+ enum {INPUT_MILLI, INPUT_CENTI};
+ enum {OUTPUT_METERS, OUTPUT_KILO};
+
+ ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO));
+ ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS));
+}
diff --git a/cpp/tests/diagnostic-messages.cpp b/cpp/tests/diagnostic-messages.cpp
index 5c7c946..dbd21a1 100644
--- a/cpp/tests/diagnostic-messages.cpp
+++ b/cpp/tests/diagnostic-messages.cpp
@@ -1,32 +1,32 @@
/*
* diagnostic-messages.cpp
*
* Created on: Oct 27, 2015
* Author: pgess
*/
#include "passmanager.h"
-#include "pass/dfgpass.h"
+#include "pass/dfapass.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate;
TEST(Diagnostic_DFA, DISABLED_recursion1){
//Error while processing recursion, There should be some diagnostic complaints
std::string code = \
"test1 = function()::[int] {\n"
" varRecursion = loop map(varRecursion->el:: int)::[int]{\n"
" el\n"
" }.\n"
" \n"
" varRecursion\n"
"}";
PassManager* man = PassManager::prepareForCode(move(code));
- DFGPass* pass = new DFGPass(man);
+ DFAPass* pass = new DFAPass(man);
pass->run();
pass->finish();
}
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
index ba12e3c..2ec0e44 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,104 +1,104 @@
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
TEST(InterfaceExternC, testAST){
std::string code = " \
interface(extern-c){ \
xml2 = library:: pkgconfig(\"libxml-2.0\"). \
\
include { \
xml2 = [\"libxml/tree.h\"] \
}. \
} \
";
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(1, parser.root.__externdata.size());
for (const ExternEntry& lib: parser.root.__externdata){
ASSERT_EQ("libxml-2.0", lib.package);
ASSERT_EQ(1, lib.headers.size());
ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
}
}
TEST(InterfaceExternC, testfetchPackageHeaders){
ExternEntry entry{"libxml-2.0", {}};
vector<string> args = ExternLayer::fetchPackageFlags(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
}
TEST(InterfaceExternC, testfetchPackageLibs){
ExternEntry entry{"libxml-2.0", {}};
vector<string> args = ExternLayer::fetchPackageLibs(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("xml2", args.at(0));
}
TEST(InterfaceExternC, testLoadLib){
std::string msgErr;
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)){
cout << msgErr;
ASSERT_EQ("", msgErr);
}
ASSERT_TRUE(true);
}
TEST(InterfaceExternC, testBSD1){
std::string code = " \n\
interface(extern-c){ \n\
libbsd = library:: pkgconfig(\"libbsd\"). \n\
\n\
include { \n\
libbsd = [\"bsd/stdlib.h\"] \n\
}. \n\
}\n"
"main= function():: int; entry{arc4random() }";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = 24;
answer = entry();
cout << answer;
ASSERT_NE(24, answer);
}
TEST(InterfaceExternC, testStructFields1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symbTree = body->findSymbol("tree");
- const TypeAnnotation& tTree = CodeScope::findDefinition(symbTree);
+ const TypeAnnotation& tTree = CodeScope::findDeclaration(symbTree).type;
const ExpandedType& t2Tree = ast.expandType(tTree);
LLVMLayer llvm(&ast);
TypeUtils utils(&llvm);
std::vector<std::string>fields = utils.getStructFields(t2Tree);
auto field = std::find(fields.begin(), fields.end(), "children");
ASSERT_TRUE(field != fields.end());
}
diff --git a/cpp/tests/sprint1-installation.cpp b/cpp/tests/installation.cpp
similarity index 94%
rename from cpp/tests/sprint1-installation.cpp
rename to cpp/tests/installation.cpp
index b4dda10..dd2e1e2 100644
--- a/cpp/tests/sprint1-installation.cpp
+++ b/cpp/tests/installation.cpp
@@ -1,22 +1,22 @@
/*
- * sprint1-installation.cpp
+ * installation.cpp
*
* Created on: 26 Feb 2016
* Author: pgess
*/
#include "passmanager.h"
#include "gtest/gtest.h"
#include <stdio.h>
using namespace std;
using namespace xreate;
//TODO replace string identifiers with Atoms in order to hold position, etc
TEST(Sprint1, test1){
const string filenameSource("scripts/testspass/sprint1-Installation1.xreate");
FILE* fileSource;
ASSERT_TRUE(fileSource = fopen(filenameSource.c_str(), "rb"));
PassManager* man = PassManager::prepareForCode(fileSource);
man->run();
}
diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp
new file mode 100644
index 0000000..d092f25
--- /dev/null
+++ b/cpp/tests/interpretation.cpp
@@ -0,0 +1,286 @@
+#include "attachments.h"
+
+using namespace xreate;
+
+#include "passmanager.h"
+#include "compilation/targetinterpretation.h"
+
+#include "gtest/gtest.h"
+#include "boost/scoped_ptr.hpp"
+
+#define private public
+#include "Parser.h"
+#include "pass/interpretationpass.h"
+
+using namespace xreate;
+using namespace xreate::compilation;
+
+TEST(Interpretation, Analysis_StatementIF_1){
+ PassManager* man = PassManager::prepareForCode(
+
+R"Code(
+ main = function::int {
+ x = "a":: string.
+
+ y = if (x=="b"):: string; interpretation(force) {
+ 1
+
+ } else {
+ 0
+ }.
+
+ y
+ }
+)Code" );
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+ Symbol symbolY = man->root->findFunction("main")->__entry->findSymbol("y");
+ InterpretationData& dataSymbolY = Attachments::get<Symbol, InterpretationData>(symbolY);
+
+ ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution);
+}
+
+TEST(Interpretation, Compilation_StatementIF_1){
+ PassManager* man = PassManager::prepareForCode(
+
+R"Code(
+ main = function::int; entry {
+ x = "a":: string.
+
+ y = if (x=="b"):: string; interpretation(force) {
+ 1
+
+ } else {
+ 0
+ }.
+
+ y
+ }
+)Code" );
+
+ man->runWithoutCompilation();
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(0, result);
+}
+
+TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1){
+ PassManager* man = PassManager::prepareForCode(
+
+R"Code(
+ main = function::int {
+ x = "a":: string; interpretation(force).
+
+ y = if (x=="b"):: string {
+ 1
+
+ } else {
+ 0
+ }.
+
+ y
+ }
+)Code" );
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+ Symbol symbolY = man->root->findFunction("main")->__entry->findSymbol("y");
+ InterpretationData& dataSymbolY = Attachments::get<Symbol, InterpretationData>(symbolY);
+
+ ASSERT_EQ(BOTH, dataSymbolY.resolution);
+ ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
+}
+
+TEST(Interpretation, Compilation_StatementIF_InterpretCondition_1){
+ PassManager* man = PassManager::prepareForCode(
+
+R"Code(
+ main = function::int; entry {
+ x = "a":: string; interpretation(force).
+
+ y = if (x=="b"):: string {
+ 1
+
+ } else {
+ 0
+ }.
+
+ y
+ }
+)Code" );
+
+ man->runWithoutCompilation();
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(0, result);
+}
+
+TEST(Interpretation, Compilation_StatementFOLD_INTERPRET_INPUT_1){
+ PassManager* man = PassManager::prepareForCode(
+
+R"Code(
+ main = function::int; entry {
+ commands = ["inc", "double", "dec"]:: [string]; interpretation(force).
+
+ loop fold(commands->comm::string, 10->operand):: int{
+ switch(comm)::int
+
+ case ("inc"){
+ operand + 1
+ }
+
+ case ("dec"){
+ operand - 1
+ }
+
+ case ("double"){
+ operand * 2
+ }
+ }
+ }
+)Code" );
+
+ man->runWithoutCompilation();
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(21, result);
+}
+
+TEST(Interpretation, StatementCall_RecursionNo_1){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ unwrap = function(data::undef, keys::undef):: undef; interpretation(force){
+ loop fold(keys->key::string, data->a):: undef {
+ a[key]
+ }
+ }
+
+ start = function::num; entry{
+ result = unwrap(
+ {
+ a = {
+ b =
+ {
+ c = "core"
+ }
+ }
+ }, ["a", "b", "c"])::undef.
+
+ result == "core"
+ }
+)Code" );
+
+ man->runWithoutCompilation();
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(1, result);
+}
+
+TEST(Interpretation, StatementCall_RecursionDirect_1){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ unwrap = function(data:: X):: Y {
+ if (data[0] == "a")::Y {0} else {unwrap(data[0])}
+ }
+
+ entry = function:: i8; entry {
+ unwrap([[[["a"]]]]):: i8; interpretation(force)
+ }
+)Code" );
+
+ man->runWithoutCompilation();
+
+ InterpretationPass* pass;
+ if (man->isPassRegistered(PassId::InterpretationPass)){
+ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
+ } else {
+ pass = new InterpretationPass(man);
+ pass->run();
+ }
+
+ InterpretationResolution resolutionActual = pass->process(man->root->findFunction("unwrap"));
+ ASSERT_EQ(BOTH, resolutionActual);
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(0, result);
+}
+
+TEST(Interpretation, StatementCall_RecursionIndirect_1){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ funcA = function(data:: X):: Y {
+ if (data == "a")::Y {0} else {funcB(data)}
+ }
+
+ funcB = function(data:: X):: Y {
+ if (data == "b")::Y {1} else {funcA(data)}
+ }
+
+ entry = function:: i8; entry {
+ funcA(""):: i8; interpretation(force)
+ }
+)Code" );
+
+ InterpretationPass* pass = new InterpretationPass(man);
+ ASSERT_DEATH(pass->run(), "Indirect recursion detected");
+}
+
+//TOTEST call indirect recursion(w/o tags)
+//TASK implement and test Loop Inf (fix acc types in coco grammar)
+
+
diff --git a/cpp/tests/loops.cpp b/cpp/tests/loops.cpp
new file mode 100644
index 0000000..7d1d5d7
--- /dev/null
+++ b/cpp/tests/loops.cpp
@@ -0,0 +1,59 @@
+#include "passmanager.h"
+
+#include "gtest/gtest.h"
+
+using namespace std;
+
+TEST(Loop, Break1){
+ string code =
+R"CODE(
+ main = function:: int; entry {
+ input = [0..10]:: [int].
+
+ loop fold(input->el::int, 0->a)::[int]
+ {
+ if (a>=5)::int {
+ 5:: int; break
+
+ } else {a+el}
+ }
+ }
+
+)CODE";
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+
+ int answerActual = funcMain();
+ ASSERT_EQ(5, answerActual);
+}
+
+TEST(Loop, InfiniteLoop1){
+
+ string code =
+R"Code(
+ interface(extern-c){
+ libFake = library:: pkgconfig("libxml-2.0").
+
+ include {
+ libFake = ["math.h"]
+ }.
+ }
+
+ main = function:: int; entry {
+ loop fold inf(0->state) :: int {
+ if (pow(2, state)==32)::int {
+ state::int; break
+
+ } else {state + 1}
+ }
+ }
+
+)Code" ;
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+
+ int answerActual = funcMain();
+ ASSERT_EQ(5, answerActual);
+}
\ No newline at end of file
diff --git a/cpp/tests/pass-Logger.cpp b/cpp/tests/pass-Logger.cpp
index 2999b73..46d4ba4 100644
--- a/cpp/tests/pass-Logger.cpp
+++ b/cpp/tests/pass-Logger.cpp
@@ -1,85 +1,85 @@
/*
* testLogging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#include <pass/loggerpass.h>
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(LoggerPass, simpleInjection){
PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");
man->runWithoutCompilation();
CompilePass* compiler = new CompilePass(man);
compiler->run();
compilation::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("test"));
ASSERT_NE(fTest, nullptr);
compilation::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
CodeScope* scopeTest = scopeUnitTest->scope;
Symbol symbX = scopeTest->findSymbol("x");
- TypeAnnotation typX = scopeTest->findDefinition(symbX);
+ TypeAnnotation typX = CodeScope::findDeclaration(symbX).type;
llvm::Value* retRaw = scopeUnitTest->compile();
llvm::BasicBlock& blockTestRaw = fTest->raw->getEntryBlock();
LLVMLayer* llvm = man->llvm;
//llvm->builder.SetInsertPoint(&blockTestRaw);
- compilation::Context params{fTest, scopeUnitTest, compiler};
+ compilation::Context params{scopeUnitTest, fTest, compiler};
LoggerPass l(man);
l.inject(symbX, params);
llvm->initJit();
int (*f)() = (int(*)()) llvm->getFunctionPointer(fTest->raw);
testing::internal::CaptureStdout();
f();
std::string&& output = testing::internal::GetCapturedStdout();
EXPECT_STREQ("10\n", output.c_str());
}
TEST(LoggerPass, simpleInjection2){
PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int; logging. x}");
man->runWithoutCompilation();
CompilePass* compiler= new CompilePass(man);
compiler->run();
LoggerPass* logger = new LoggerPass(man);
logger->initDependencies(compiler);
logger->run();
man->llvm->initJit();
man->llvm->print();
int (*f)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction());
testing::internal::CaptureStdout();
f();
std::string&& output = testing::internal::GetCapturedStdout();
EXPECT_STREQ("10\n", output.c_str());
}
TEST(LoggerPass, simpleInjection3){
FILE* input = fopen("scripts/cases/log.xreate","r");
assert(input);
std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
fclose(input);
}
diff --git a/cpp/tests/testClangAPI.cpp b/cpp/tests/testClangAPI.cpp
index 0005ad2..a1d96ce 100644
--- a/cpp/tests/testClangAPI.cpp
+++ b/cpp/tests/testClangAPI.cpp
@@ -1,190 +1,197 @@
//
// Created by pgess on 4/16/15.
//
#include "gtest/gtest.h"
#include <llvm/IR/DerivedTypes.h>
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/CodeGen/CodeGenAction.h"
-#include "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenTypes.h"
-#include "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenModule.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "llvm/IR/LLVMContext.h"
#include "clang/Basic/TargetInfo.h"
#include <boost/format.hpp>
+#include "../../vendors/clang-codegen-private-3.8/CodeGenModule.h"
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
/*
class PrintFunctionsConsumer : public ASTConsumer {
public:
bool HandleTopLevelDecl(DeclGroupRef DG) override {
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
const Decl *D = *i;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
return true;
}
};
class PFAction : public ASTFrontendAction {
public:
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return llvm::make_unique<PrintFunctionsConsumer>();
}
};
*/
class PrinterType : public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
ASTContext* C = Result.Context;
llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
QualType Ty = decl->getUnderlyingType();
llvm::errs() << "<" << Ty.getAsString() << ">" ;
- CodeGenOptions *CGO = new CodeGenOptions;
-
- const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
- CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
+ M->setDataLayout(C->getTargetInfo().getDataLayoutString());
+ CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(
+ *C,
+ *(new HeaderSearchOptions()),
+ *(new PreprocessorOptions()),
+ *(new CodeGenOptions()),
+ *M,
+ C->getDiagnostics());
llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
rawTy->dump();
results.push_back(rawTy);
}
}
std::vector<llvm::Type*> results;
};
class PrinterFunction: public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
- QualType Ty = decl->getType();
-
- llvm::errs() << "<" << Ty.getAsString() << ">" ;
- ASTContext* C = Result.Context;
- llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
- CodeGenOptions *CGO = new CodeGenOptions;
-
- const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
- CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
-
- llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
-
- //const clang::FunctionType* Ty = decl->getType()->getAs<clang::FunctionType>();
- llvm::FunctionType* rawFuncTy = llvm::dyn_cast<llvm::FunctionType>(rawTy);
- rawFuncTy->dump();
- results.push_back(rawFuncTy);
-
- /*
- llvm::Function* fDeclaration = llvm::Function::Create(rawFuncTy, llvm::GlobalValue::ExternalLinkage, "xxxx", M);
- fDeclaration->dump();
- */
+ QualType Ty = decl->getType();
+
+ llvm::errs() << "<" << Ty.getAsString() << ">" ;
+ ASTContext* C = Result.Context;
+ llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
+
+ CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(
+ *C,
+ *(new HeaderSearchOptions()),
+ *(new PreprocessorOptions()),
+ *(new CodeGenOptions()),
+ *M,
+ C->getDiagnostics());
+
+ llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
+
+ //const clang::FunctionType* Ty = decl->getType()->getAs<clang::FunctionType>();
+ llvm::FunctionType* rawFuncTy = llvm::dyn_cast<llvm::FunctionType>(rawTy);
+ rawFuncTy->dump();
+ results.push_back(rawFuncTy);
+
+ /*
+ llvm::Function* fDeclaration = llvm::Function::Create(rawFuncTy, llvm::GlobalValue::ExternalLinkage, "xxxx", M);
+ fDeclaration->dump();
+ */
}
}
std::vector<llvm::Type*> results;
};
//DEBT fix dependency on clasp/gcc version
vector<string> argv = {
"-I/usr/include/libxml2"
,"-I/usr/local/include"
,"-I/usr/lib/llvm-3.6/lib/clang/3.6.0/include"
,"-I/usr/include"
};
TEST(ClangAPI, testExternalType)
{
//,, "-I/usr/include/linux"
// "-cc1", "-emit-pch", "-disable-free", "-disable-llvm-verifier", "-mrelocation-model", "static",
// "-mthread-model", "posix", "-mdisable-fp-elim", "-fmath-errno", "-masm-verbose",
// "-mconstructor-aliases", "-munwind-tables", "-fuse-init-array", "-target-cpu", "x86-64", "-target-linker-version", "2.25",
//"-dwarf-column-info", "-resource-dir", "/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0",
//"clang", "--",
/*
int argc= argv.size();
llvm::cl::OptionCategory cat("aaaa");
LLVMInitializeNativeTarget();
CommonOptionsParser op(argc, &*(argv.begin()), cat);
ClangTool tool(op.getCompilations(), op.getSourcePathList());
*/
auto matcherType =
typedefDecl(hasName("xmlNodePtr")).bind("typename");
MatchFinder finder;
PrinterType printer;
finder.addMatcher(matcherType, &printer);
std::string code = (boost::format("#include \"%1%\"") % ("libxml/tree.h")).str();
//runToolOnCodeWithArgs(newFrontendActionFactory(&finder).get()->create(), code, argv);
std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
ASTContext & context = ast->getASTContext();
finder.matchAST(context);
string signatureExpected = "%struct._xmlNode*";
ASSERT_EQ(1, printer.results.size());
llvm::Type* tyActual = printer.results.at(0);
string strActual;
llvm::raw_string_ostream ss(strActual);
tyActual->print(ss);
ASSERT_EQ(signatureExpected, ss.str());
//int x = tool.run(newFrontendActionFactory(&finder).get());
}
TEST(ClangAPI, testExternalFunction){
auto matcherType = functionDecl(hasName("arc4random")).bind("function");
MatchFinder finder;
PrinterFunction printer;
finder.addMatcher(matcherType, &printer);
std::string code = (boost::format("#include \"%1%\"") % ("bsd/stdlib.h")).str();
std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
ASTContext & context = ast->getASTContext();
finder.matchAST(context);
string signatureExpected = "i32 ()";
ASSERT_EQ(1, printer.results.size());
llvm::Type* tyActual = printer.results.at(0);
string strActual;
llvm::raw_string_ostream ss(strActual);
tyActual->print(ss);
ASSERT_EQ(signatureExpected, ss.str());
}
diff --git a/cpp/tests/testExploitation.cpp b/cpp/tests/testExploitation.cpp
new file mode 100644
index 0000000..88cbc4d
--- /dev/null
+++ b/cpp/tests/testExploitation.cpp
@@ -0,0 +1,49 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+#include "passmanager.h"
+
+#include "gtest/gtest.h"
+#include <boost/scoped_ptr.hpp>
+
+using namespace xreate;
+using namespace std;
+
+//TEST(Exploitation, append1){
+// std::string program =
+//R"CODE(
+//
+//test1 = function :: num; entry {
+// appendA() + appendB()
+//}
+//
+//appendA = function:: num {
+// append("a", "/tmp/test1.txt")
+//}
+//
+//appendB = function:: num {
+// append("b", "/tmp/test1.txt")
+//}
+//
+//append = function(msg::string, filename::string):: num
+//{
+// f = initialize(filename):: FILE.
+//
+// fprintf(f, msg)
+//}
+//
+//)CODE";
+//
+// boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
+// man->runWithoutCompilation();
+//}
+
+#include <iostream>
+#include <gringo/scripts.hh>
+#include "clasplayer.h"
+
+TEST(Exploitation, clasp1){
+}
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 5815c3b..97e2354 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,167 +1,167 @@
/*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(Types, DependantTypes1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeXmlNode = program->root->findType("XmlNode");
ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator);
ASSERT_EQ(2, typeXmlNode->__operands.size());
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value);
}
TEST(Types, DependantTypes2) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Template = type Template(Leaf) [Leaf, [Leaf[content]]]."
"Concrete = type alias Template(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
}
TEST(Types, TreeType1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
auto typeLink = typeConcrete->__operands.at(1).__operands.at(0);
ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId);
}
TEST(Types, TreeType1LLvm){
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
TEST(Types, ArrayOfExternal1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symb = body->findSymbol("childrenRaw");
- const TypeAnnotation& t = CodeScope::findDefinition(symb);
+ const TypeAnnotation& t = CodeScope::findDeclaration(symb).type;
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
}
TEST(Types, ExternType1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symbTree = body->findSymbol("tree");
- const TypeAnnotation& t = CodeScope::findDefinition(symbTree);
+ const TypeAnnotation& t = CodeScope::findDeclaration(symbTree).type;
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
}
TEST(Types, ast_VariantType1){
string&& code =
" colors = type variant (RED, BLUE, GREEN).\n"
" test = function:: colors; entry {GREEN}";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typ = program->root->findType("colors");
EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
Expression eRed = program->root->findFunction("test")->getEntryScope()->__body;
EXPECT_EQ(Expression::VARIANT, eRed.__state);
const ExpandedType& typ2 = program->root->expandType(eRed.type);
EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
program->run();
}
TEST(Types, full_VariantType_Switch1){
string&& code =
" colors = type variant (RED, BLUE, GREEN).\n"
" test = function:: colors; entry {GREEN}"
"main = function:: int; entry {\n"
" switch(test():: color)\n"
" case GREEN {0}\n"
" case default {1}\n"
"}";
PassManager* man = PassManager::prepareForCode(move(code));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(0, main());
}
-//TEST string type
+//TOTEST string type
diff --git a/documentation/Articles/gestalts.remarkup b/documentation/Articles/gestalts.remarkup
index 338b33f..39efc54 100644
--- a/documentation/Articles/gestalts.remarkup
+++ b/documentation/Articles/gestalts.remarkup
@@ -1,12 +1,12 @@
==Computational gestalts==
There are number of commonly accepted concepts that are redefined or reevaluated in xreate.
* Interface is comprised of common subset of features supported by all concrete implementations.
See [[concepts/containers]]
* Entity's annotations(like function, objects annotations) are exposed to and could be intospected by client code in other words by caller.
Most usefull is exposing of caller annotations to a callee code.
*Lazy/eager execution opposition.
It's possible to determine which sites of using resource should treat it as lazy resource or eager otherwise.
- See [[concepts/usage]] for details.
\ No newline at end of file
+ See [[concepts/exploitation]] for details.
\ No newline at end of file
diff --git a/documentation/Aspects/highlevel.remarkup b/documentation/Aspects/highlevel.remarkup
new file mode 100644
index 0000000..f724e71
--- /dev/null
+++ b/documentation/Aspects/highlevel.remarkup
@@ -0,0 +1,5 @@
+High-level:
+
+*Focus on current task
+*Program Addtitivity
+*Reduce refactoring needs
\ No newline at end of file
diff --git a/documentation/Aspects/refactoring.remarkup b/documentation/Aspects/refactoring.remarkup
index 6b1531f..5623b2a 100644
--- a/documentation/Aspects/refactoring.remarkup
+++ b/documentation/Aspects/refactoring.remarkup
@@ -1 +1,4 @@
-Refactoring - ability to quiclky transform and apply software to different tasks
\ No newline at end of file
+Refactoring - ability to quiclky adjust and apply software to a different tasks
+
+reduce refactoring dimensions by 2.
+2D refactoring: (rigid-soft software axe, memory-computation on the fly axe) is unnecessary and covered by additive annotations.
\ No newline at end of file
diff --git a/documentation/Concepts/usage.remarkup b/documentation/Concepts/exploitation.remarkup
similarity index 57%
rename from documentation/Concepts/usage.remarkup
rename to documentation/Concepts/exploitation.remarkup
index 67f3a6b..6589240 100644
--- a/documentation/Concepts/usage.remarkup
+++ b/documentation/Concepts/exploitation.remarkup
@@ -1,10 +1,11 @@
-Analyzing CFG to find first/last usage of resources:
+Analyzing CFG to find common resource exploitation patterns,
+like to determine sites of first and last usage of resources in order to check(provide) safe initialization or releasing.
**Usecases:**
* resource using in loop: acquire resource right before loop, and freeing right after that.
* group of probable first/last using: every site in the group should treat resource as lazy(with safety check),
and eager otherwise
**Examples:**
* appending to a file
* memory management
\ No newline at end of file
diff --git a/documentation/Internal/todo.remarkup b/documentation/Internal/todo.remarkup
new file mode 100644
index 0000000..37344cf
--- /dev/null
+++ b/documentation/Internal/todo.remarkup
@@ -0,0 +1,2 @@
+* syntax/switch: mention about a case body scope is a subscope (or a child) of a case parameters scope
+ (as of now expression resolution only, not for annotations resolution)
diff --git a/documentation/Syntax/control-flow-statements.remarkup b/documentation/Syntax/control-flow-statements.remarkup
index 4901695..b9deedd 100644
--- a/documentation/Syntax/control-flow-statements.remarkup
+++ b/documentation/Syntax/control-flow-statements.remarkup
@@ -1,132 +1,132 @@
==Control flow statements==
These statements control execution flow of a program.
=== If-Else ===
The If-Else statement executes a //main-expression// branch if a specified condition is true.
If the condition is false, //alternative-expression// branch will be executed.
SYNTAX: if (//condition//):: //type//
{
[//declaration//. [ //declaration//.]... ]
//main-expression//
} else {
[//declaration//. [ //declaration//.]... ]
//alternative-expression//
}
//condition//
Bool type expression(see [[types]]) in order to decide which branch of IF-ELSE statement should be executed.
//main expression//
Executed if condition yelds ##true##
//alternative expression//
Executed if condition yelds ##false##
Example:
x = if (y<0) :: num
{-1} else {1}
===Switch===
Executes one of the given branches depending on condition.
-SYNTAX: switch (//condition// :: //type-of-condition//)
+SYNTAX: switch (//condition//) :: //type-of-switch//
[case //variant// {
[declaration. [ declaration.]... ]
//transformation-expression//
}]...
//condition//
Expression to determing which case branch should be executed
-//type-of-condition//
-Type of condition result
+//type-of-switch//
+Type of switch result
//variant//
Expression to compare against //condition//.
If the //condition// evaluation result corresponds to the //variant// then a relevant branch is executed.
Special label **default** is allowed and designates default branch executed if no other branches are selected.
//transformation-expression//
Determines result of a switch statement if relevant branch is selected based on //condition//.
Example:
x = 2:: num.
- y = switch (x:: string)
+ y = switch (x) ::string
case 0 {"zero"}
case 1 {"one"}
case 2 {"two"}
case default {"unknown"}
===Map loop===
Iterates over input collection and stores result in another collection.
Every input collection's value transformed using //transformation-expression//.
SYNTAX: loop map ( //input-collection// -> //alias// :: //type-of-element//) :: //type-of-collection//
{
[declaration. [ declaration.]... ]
//transformation-expression//
}
//input-collection//
Variable or expression to designate collection for transformation
//alias//
Variable name to designate current collection element in scope of inner code block
//type-of-element//
Type of collection's element
//type-of-collection//
Type of resulting transformed collection
//transformation-expression//
Transformation applied to an every collection element
Example:
input = [1..10].
twice = loop map (input -> x:: num):: [num]
{ 2 * x }
===Fold loop===
Iterates over input collection in order to accumulate result by applying //transformation-expression// to each element and intermediate accumulator.
SYNTAX: loop fold (//input-collection// -> //alias// :: //type-of-element//, //accumulator//->//accumulator-alias//) :: //type-of-accumulator//
{
[declaration. [ declaration.]... ]
//transformation-expression//
}
//input-collection//
Variable or expression to designate collection
//alias//
Variable name to designate current collection element in scope of inner code block
//type-of-element//
Type of collection's element
//accumulator//
Expression to evaluate initial value of accumulator
//accumulator-alias//
Variable name to designate current value of accumulator in scope of inner code block
//type-of-accumulator//
Type of folding result
//transformation-expression//
Expression applied to an every collection's element and current state of accumulator in order to
calculate accumulator value for next step of iteration.
This is an example:
numbers = [1..10] :: [num].
sumOfNumbers = loop fold(numbers->x; 0->result)
{result + x}
diff --git a/documentation/Syntax/index.remarkup b/documentation/Syntax/index.remarkup
index 6e2d7e1..5467fe4 100644
--- a/documentation/Syntax/index.remarkup
+++ b/documentation/Syntax/index.remarkup
@@ -1 +1,22 @@
-This section devoted to a syntax description
\ No newline at end of file
+This section devoted to a syntax description
+
+In general, syntax follows SSA form: every symbol has a single site of assignment.
+
+SYNTAX:
+{
+ [declaration.]...
+ //result-expression//
+}
+
+Example:
+ {
+ t = Pi / 2 :: num.
+ left = sin(2 * t):: num.
+ right = cos(8 * t):: num.
+
+ left + right // result expression
+ }
+
+SSA form being very simple and intuitive, however does not posssess expressiveness enough to cope
+with more compilcated cases like [[loops | control-flow-statements]]. That's why there are specific syntax constructions
+provided in order to keep basic SSA syntax but with different semantics suited for those compicated cases.
\ No newline at end of file
diff --git a/geany-plugin-sort.lua b/geany-plugin-sort.lua
new file mode 100644
index 0000000..bee8616
--- /dev/null
+++ b/geany-plugin-sort.lua
@@ -0,0 +1,25 @@
+function split(str, pat)
+ local t = {} -- NOTE: use {n = 0} in Lua-5.0
+ local fpat = "(.-)" .. pat
+ local last_end = 1
+ local s, e, cap = str:find(fpat, 1)
+ while s do
+ if s ~= 1 or cap ~= "" then
+ table.insert(t,cap)
+ end
+ last_end = e+1
+ s, e, cap = str:find(fpat, last_end)
+ end
+ if last_end <= #str then
+ cap = str:sub(last_end)
+ table.insert(t, cap)
+ end
+ return t
+end
+
+geany.select(0, geany.length())
+local text = geany.selection()
+local lines = split(text, " ")
+table.sort(lines)
+local output = table.concat(lines, "\n")
+geany.selection(output)
diff --git a/install-dependencies-opensuse b/install-dependencies-opensuse
new file mode 100755
index 0000000..cebf18d
--- /dev/null
+++ b/install-dependencies-opensuse
@@ -0,0 +1,39 @@
+#!/bin/sh
+CURRENT_DIR=$PWD
+
+sudo zypper in tbb-devel cmake llvm-devel llvm-clang-devel git bison re2c scons unzip gcc-c++ libgtest0 googletest-devel boost-devel libxml2-devel
+
+# COCO
+mkdir /opt/coco-cpp/
+cd /opt/coco-cpp/
+if [ ! -f ./CocoSourcesCPP.zip ]; then
+ wget http://www.ssw.uni-linz.ac.at/Coco/CPP/CocoSourcesCPP.zip
+ unzip ./CocoSourcesCPP.zip
+fi
+
+g++ *.cpp -o Coco -g -Wall
+
+# POTASSCO
+mkdir /opt/potassco/
+cd /opt/potassco/
+git clone https://github.com/potassco/clingo.git
+cd clingo
+sed -i "s/CXXFLAGS = \[\(.*\)\]/CXXFLAGS = \['-fPIC', \1\]/" build/debug.py
+scons --build-dir=debug
+
+sed -i "s/CXXFLAGS = \[\(.*\)\]/CXXFLAGS = \['-fPIC', \1\]/" build/release.py
+scons --build-dir=release
+
+
+cd $CURRENT_DIR
+mkdir ./build/xreate-tests-debug
+cd ./build/xreate-tests-debug
+cmake -DBUILD_XREATE_TESTS=1 -build ../../cpp
+
+make -j2
+
+
+
+
+
+
diff --git a/scripts/containers/containers-indexed-1.xreate b/scripts/containers/containers-indexed-1.xreate
new file mode 100644
index 0000000..69fd40c
--- /dev/null
+++ b/scripts/containers/containers-indexed-1.xreate
@@ -0,0 +1,29 @@
+//Expose indexes signature(anonymous):
+ a:: [(string, string, num)]; byName <- index(0); byCity <- index(1);
+ byNameAndCity <- index(0, 1).
+
+//Expose index signature(named)
+ type Record =
+ {
+ name:: string,
+ city:: string,
+ age:: num
+ }.
+
+ b:: [Record]; byName <- index(Record.name).
+
+//Use determined index
+ x = a["Rabat"]:: Record; index(byCity).
+
+//Determined syntax(view)
+ viewByCity = a:: [Record]; index(byCIty).
+ x = viewByCity["Rabat"].
+
+//Determined index(inline)
+ x = a[byCity: "Rabbat"]:: Record.
+
+
+//Undefined index
+ x = a[{city: "Rabat"}] :: Record. <- index byCity should be deduced
+ x = a[{name: "Hind", city: "Rabat"}]
+
diff --git a/scripts/dsl/regexps.xreate b/scripts/dsl/regexps.xreate
new file mode 100644
index 0000000..b02d3e1
--- /dev/null
+++ b/scripts/dsl/regexps.xreate
@@ -0,0 +1,81 @@
+===========================
+ DATA
+
+patternAB = {
+ sequence: [
+ {zeroOrMore: 'a'},
+ {text: 'b'},
+ ]
+}
+
+mod sequence{
+[
+ mod zeroOrMore (text("a")),
+ matcher text("b")
+]
+)
+
+
+==========================
+ HANDLERS
+
+ case matcher:: mod sequence
+match = function(text, matcher) {
+ loop fold(node-> matcher, 0->pos){
+ n = match(matcher, mid(text, pos, length(text))).// <-- every time length?
+
+ if (pos == pos_FAIL || n == pos_FAIL){
+ pos_FAIL:: break
+ } else {
+ pos+n
+ }
+ }
+}
+
+ case matcher:: mod zeroOrMore (Dereferenced)
+match= function(text, matcher){
+ matcherChild = matcher:: Dereferenced. //<--- extract child(unification)
+
+ loop fold inf(0->pos, n==pos_FAIL){ //<--- infinite loop?
+ n = match(matcherChild, mid(text, pos, length(text))).
+
+ if (n == pos_FAIL:: break){
+ pos
+
+ } else {
+ pos+n
+ }
+ }
+}
+
+ case matcher:: matcher text
+match = function(text, matcher) {
+ pattern = matcher:: string.
+
+ if (length(text)>0 &&
+ length(pattern) <= length(text) &&
+ mid(text, 0, length(pattern)) == pattern)
+ {
+ length(pattern);
+
+ } else {
+ pos_FAIL;
+ }
+}
+
+match = function(text::string, pattern::string)::string{
+ n= match(pattern, text).
+
+ if (n != pos_FAIL)
+ {mid(text, 0, n)}
+ else
+ {text_FAIL}
+}
+
+=================================
+ CLIENT
+
+test = function(){
+ match(patternAB, "aaaaab").
+ match(patternAB, "baaaaa").
+}
diff --git a/scripts/exploitation/test1-fixture.lp b/scripts/exploitation/test1-fixture.lp
new file mode 100644
index 0000000..491a935
--- /dev/null
+++ b/scripts/exploitation/test1-fixture.lp
@@ -0,0 +1,50 @@
+function(test1).
+bind_func(test1, entry).
+function(appendA; appendB; append).
+scope(0..3).
+%scope tags: no tags at all
+
+% Static analysis: CFA
+cfa_parent(0, function(test1)).
+cfa_parent(1, function(appendA)).
+cfa_parent(2, function(appendB)).
+cfa_parent(3, function(append)).
+cfa_call(0, appendA).
+cfa_call(0, appendB).
+cfa_call(1, append).
+cfa_call(2, append).
+
+% Static analysis: DFA
+dfa_connection((2, 3), (anonym(0), 1), weak). %append:msg - anonym(0)
+dfa_connection((3, 3), (anonym(1), 1), weak). %append:filename - anonym(1)
+dfa_connection((0, 1), (0, 3), strong). %appendA: *retv - append: *retv
+dfa_connection((2, 3), (anonym(2), 2), weak). %append:msg - anonym(2)
+dfa_connection((3, 3), (anonym(3), 2), weak). %append:filename - anonym(3)
+dfa_connection((0, 2), (0, 3), strong). %appendB: *retv - append: *retv
+
+v((anonym(0), 1)). %anonym(0)
+v((anonym(1), 1)). %anonym(1)
+v((0, 2)). %appendB: *retv
+v((anonym(2), 2)). %anonym(2)
+v((anonym(3), 2)). %anonym(3)
+v((0, 3)). %append: *retv
+v((2, 3)). %append:msg
+v((3, 3)). %append:filename
+
+cfa_forwdom(0, range(0, 7)).
+cfa_forwdom(1, range(1, 2)).
+cfa_forwdom(2, range(5, 6)).
+cfa_forwdom(3, range(3, 4)).
+cfa_postdom(0, range(3, 4)).
+cfa_postdom(1, range(1, 2)).
+cfa_postdom(2, range(5, 6)).
+cfa_postdom(3, range(0, 7)).
+
+% EXPLOITATION TAGS:
+bind((3,3), exploitation_initialized(file)).
+
+% BIND ACTUAL DATA FOR STATIC SYMBOLS
+bind((anonym(0), 1), static(data(a))). %anonym(0)
+bind((anonym(1), 1), static(data(tmp_test1_txt))). %anonym(1)
+bind((anonym(2), 2), static(data(b))). %anonym(2)
+bind((anonym(3), 2), static(data(tmp_test1_txt))). %anonym(3)
diff --git a/scripts/exploitation/test1.xreate b/scripts/exploitation/test1.xreate
new file mode 100644
index 0000000..cc8eced
--- /dev/null
+++ b/scripts/exploitation/test1.xreate
@@ -0,0 +1,38 @@
+test1 = function :: int; entry {
+ appendA() + appendB
+}
+
+appendA = function:: int {
+ append("a", "/tmp/test1.txt")
+}
+
+appendB = function:: int {
+ append("b", "/tmp/test1.txt")
+}
+
+append:: function(message::string, filename::string):: int,
+{
+ f = initialize(filename):: FILE.
+
+ fprintf(f, message)
+}
+
+======================================================
+initialize(filename:: string; exploitation_file_initialized)
+{
+ // get cached descriptor for FileName:
+ files:: cached(exploitation_files).
+
+ files[filename]
+}
+
+attach scope:: openFile(FileName) {
+ fid = fopen(FileName).
+ (FileName, fid):: cached(exploitation_files).
+}
+
+attach scope:: closeFile(FileName){
+ files:: cached(exploitation_files).
+ fid = files[FileName].
+ fclose(fid)
+}
diff --git a/scripts/metatests/aux/graphs_trees_depth-test1.lp b/scripts/metatests/aux/graphs_trees_depth-test1.lp
new file mode 100644
index 0000000..00f89f7
--- /dev/null
+++ b/scripts/metatests/aux/graphs_trees_depth-test1.lp
@@ -0,0 +1,9 @@
+#include "core/aux/graphs_trees_depth.lp".
+
+graphs_node(a; b; c; d).
+graphs_tree_depends(b,a).
+graphs_tree_depends(c,a).
+graphs_tree_depends(d, a).
+graphs_tree_depends(d, c).
+
+#show graphs_tree_depth/2.
\ No newline at end of file
diff --git a/scripts/metatests/aux/graphs_trees_depth-test2.lp b/scripts/metatests/aux/graphs_trees_depth-test2.lp
new file mode 100644
index 0000000..630d807
--- /dev/null
+++ b/scripts/metatests/aux/graphs_trees_depth-test2.lp
@@ -0,0 +1,8 @@
+#include "core/aux/graphs_trees_depth.lp".
+
+graphs_node(a; b; c).
+graphs_tree_depends(b,a).
+graphs_tree_depends(b,c).
+graphs_tree_depends(c,b).
+
+#show graphs_tree_depth/2.
\ No newline at end of file
diff --git a/scripts/metatests/exploitation-test1.lp b/scripts/metatests/exploitation-test1.lp
new file mode 100644
index 0000000..c217721
--- /dev/null
+++ b/scripts/metatests/exploitation-test1.lp
@@ -0,0 +1,10 @@
+#include "core/precompilation.lp".
+#include "core/exploitation.lp".
+
+#include "scripts/exploitation/test1-fixture.lp".
+
+#show bind/2.
+#show expl_sites/2.
+#show expl_resources/2.
+#show expl_parent/2.
+#show bind_scope/2.
diff --git a/scripts/metatests/tests1-context-latecontext3.lp b/scripts/metatests/tests1-context-latecontext3.lp
index 28c84be..f344ff0 100644
--- a/scripts/metatests/tests1-context-latecontext3.lp
+++ b/scripts/metatests/tests1-context-latecontext3.lp
@@ -1,39 +1,75 @@
-#include "context-latecontext3.lp".
-function(a;b;r0; r1; sink; fnOut).
-scope(0..5).
+#include "core/control-context-v3.lp".
+function(a1;b1;a2;b2;a3;b3; sink; fnOut).
+scope(0..7).
%CFA
-cfa_parent(0, function(a)).
-cfa_parent(1, function(b)).
-cfa_parent(2, function(r0)).
-cfa_parent(3, function(r1)).
-cfa_parent(4, function(sink)).
-cfa_parent(5, function(fnOut)).
-
-cfa_function_specializations(fnOut, keys(keyA0)).
-cfa_function_specializations(fnOut, keys(keyA1)).
-cfa_function_specializations(fnOut, keys(keyB0)).
-cfa_function_specializations(fnOut, keys(keyB1)).
-
-
-cfa_call(0, r0).
-cfa_call(0, r1).
-cfa_call(1, r0).
-cfa_call(1, r1).
-cfa_call(2, sink).
-cfa_call(3, sink).
-cfa_call(4, fnOut).
+cfa_parent(0, function(a1)).
+cfa_parent(1, function(b1)).
+cfa_parent(2, function(a2)).
+cfa_parent(3, function(b2)).
+cfa_parent(4, function(a3)).
+cfa_parent(5, function(b3)).
+
+cfa_parent(6, function(sink)).
+cfa_parent(7, function(fnOut)).
+
+cfa_function_specializations(fnOut, keys(keyA1A2A3)).
+cfa_function_specializations(fnOut, keys(keyA1A2B3)).
+cfa_function_specializations(fnOut, keys(keyA1B2A3)).
+cfa_function_specializations(fnOut, keys(keyA1B2B3)).
+cfa_function_specializations(fnOut, keys(keyB1A2A3)).
+cfa_function_specializations(fnOut, keys(keyB1A2B3)).
+cfa_function_specializations(fnOut, keys(keyB1B2A3)).
+cfa_function_specializations(fnOut, keys(keyB1B2B3)).
+
+
+cfa_call(0, a2).
+cfa_call(0, b2).
+cfa_call(1, a2).
+cfa_call(1, b2).
+cfa_call(2, a3).
+cfa_call(2, b3).
+cfa_call(3, a3).
+cfa_call(3, b3).
+cfa_call(4, sink).
+cfa_call(5, sink).
+cfa_call(6, fnOut).
%context rules
% r0: keyA->keyA0, keyB->keyB0
% r1: keyA->keyA1, keyB->keyB1
-bind_scope(2, keys(keyA0), Info) :- bind_scope(2, keys(keyA), Info).
-bind_scope(2, keys(keyB0), Info) :- bind_scope(2, keys(keyB), Info).
-bind_scope(3, keys(keyA1), Info) :- bind_scope(3, keys(keyA), Info).
-bind_scope(3, keys(keyB1), Info) :- bind_scope(3, keys(keyB), Info).
+bind_scope(2, keys(keyA1A2), Info) :- bind_scope(2, keys(keyA1), Info).
+bind_scope(2, keys(keyB1A2), Info) :- bind_scope(2, keys(keyB1), Info).
+bind_scope(3, keys(keyA1B2), Info) :- bind_scope(3, keys(keyA1), Info).
+bind_scope(3, keys(keyB1B2), Info) :- bind_scope(3, keys(keyB1), Info).
+
+bind_scope(4, keys(keyA1A2A3), Info):-bind_scope(4, keys(keyA1A2), Info).
+bind_scope(4, keys(keyB1A2A3), Info):-bind_scope(4, keys(keyB1A2), Info).
+bind_scope(4, keys(keyA1B2A3), Info):-bind_scope(4, keys(keyA1B2), Info).
+bind_scope(4, keys(keyB1B2A3), Info):-bind_scope(4, keys(keyB1B2), Info).
+
+bind_scope(5, keys(keyA1A2B3), Info):-bind_scope(5, keys(keyA1A2), Info).
+bind_scope(5, keys(keyB1A2B3), Info):-bind_scope(5, keys(keyB1A2), Info).
+bind_scope(5, keys(keyA1B2B3), Info):-bind_scope(5, keys(keyA1B2), Info).
+bind_scope(5, keys(keyB1B2B3), Info):-bind_scope(5, keys(keyB1B2), Info).
+
%initial context
-keys(keyA; keyB; keyA0; keyA1; keyB0; keyB1).
+keys(
+ keyA1; keyB1;
+ keyA1A2;
+ keyB1A2;
+ keyA1B2;
+ keyB1B2;
+ keyA1A2A3;
+ keyA1A2B3;
+ keyA1B2A3;
+ keyA1B2B3;
+ keyB1A2A3;
+ keyB1A2B3;
+ keyB1B2A3;
+ keyB1B2B3
+).
-bind_scope(0, keys(keyA), strong).
-bind_scope(1, keys(keyB), strong).
+bind_scope(0, keys(keyA1), strong).
+bind_scope(1, keys(keyB1), strong).
diff --git a/scripts/precompilation-1.lp b/scripts/precompilation-1.lp
new file mode 100644
index 0000000..1c14007
--- /dev/null
+++ b/scripts/precompilation-1.lp
@@ -0,0 +1,11 @@
+%%DATA EMBEDDING:
+ %bind(S, static(Data)):- Data= ref(_); bind(SymbolFrom, static(Data)); dfa_connection(S, SymbolFrom, _).
+ %bind(S, static(ref(Root))):- Data= data(_); bind(Root, static(Data)); dfa_connection(S, Root, _).
+
+%% SCHEME:
+ % bind(S, static).
+ % dfa_static(S, data(Data))
+ % dfa_static(S, ref(RootSymbol))
+
+bind(S2, static) :- bind(S1, static): dfa_connection(S2, S1, _).
+
diff --git a/scripts/metatests/(invalid)tests-context.lp b/scripts/sprint1_environment/(invalid)tests-context.lp
similarity index 100%
rename from scripts/metatests/(invalid)tests-context.lp
rename to scripts/sprint1_environment/(invalid)tests-context.lp
diff --git a/scripts/metatests/context-latecontext1.lp b/scripts/sprint1_environment/context-latecontext1.lp
similarity index 100%
rename from scripts/metatests/context-latecontext1.lp
rename to scripts/sprint1_environment/context-latecontext1.lp
diff --git a/scripts/metatests/context-latecontext2.lp b/scripts/sprint1_environment/context-latecontext2.lp
similarity index 100%
rename from scripts/metatests/context-latecontext2.lp
rename to scripts/sprint1_environment/context-latecontext2.lp
diff --git a/scripts/metatests/context-latecontext3.lp b/scripts/sprint1_environment/context-latecontext3.lp
similarity index 100%
rename from scripts/metatests/context-latecontext3.lp
rename to scripts/sprint1_environment/context-latecontext3.lp
diff --git a/scripts/sprint1_environment/dependencies.lp b/scripts/sprint1_environment/dependencies.lp
deleted file mode 100644
index 5dab87b..0000000
--- a/scripts/sprint1_environment/dependencies.lp
+++ /dev/null
@@ -1,9 +0,0 @@
-node(a; b; c; d).
-depends(b,a).
-depends(c,a).
-depends(d, a).
-depends(d, c).
-
-level(X, 0) :- not depends(X, _); node(X).
-
-level(X, LEVEL):- LEVEL = #max{L+1, level(Y, L): level(Y, L), depends(X, Y)}; node(X); LEVEL > 0.
diff --git a/scripts/sprint1_environment/dependencies.lp b/scripts/sprint1_environment/dependencies.lp
new file mode 120000
index 0000000..5d00940
--- /dev/null
+++ b/scripts/sprint1_environment/dependencies.lp
@@ -0,0 +1 @@
+/private/prg/code/xreate/core/graphs_trees_depth.lp
\ No newline at end of file
diff --git a/scripts/sprint1_environment/solution-latecontext-3layers b/scripts/sprint1_environment/solution-latecontext-3layers
new file mode 100644
index 0000000..2d13d91
--- /dev/null
+++ b/scripts/sprint1_environment/solution-latecontext-3layers
@@ -0,0 +1,192 @@
+
+bind_function_demand(a2,dependency(dependency(specialization(fnOut,6),4),2))
+bind_function_demand(a2,dependency(dependency(specialization(fnOut,6),5),2))
+bind_function_demand(a2,dependency(specialization(fnOut,6),2))
+bind_function_demand(a3,dependency(specialization(fnOut,6),4))
+bind_function_demand(b2,dependency(dependency(specialization(fnOut,6),4),3))
+bind_function_demand(b2,dependency(dependency(specialization(fnOut,6),5),3))
+bind_function_demand(b2,dependency(specialization(fnOut,6),3))
+bind_function_demand(b3,dependency(specialization(fnOut,6),5))
+bind_function_demand(sink,specialization(fnOut,6))
+
+bind_scope_demand(2,dependency(dependency(specialization(fnOut,6),4),2))
+bind_scope_demand(2,dependency(dependency(specialization(fnOut,6),5),2))
+bind_scope_demand(2,dependency(specialization(fnOut,6),2))
+bind_scope_demand(3,dependency(dependency(specialization(fnOut,6),4),3))
+bind_scope_demand(3,dependency(dependency(specialization(fnOut,6),5),3))
+bind_scope_demand(3,dependency(specialization(fnOut,6),3))
+bind_scope_demand(4,dependency(specialization(fnOut,6),4))
+bind_scope_demand(5,dependency(specialization(fnOut,6),5))
+bind_scope_demand(6,specialization(fnOut,6))
+
+bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),4),2),weak(0))
+bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),4),3),weak(0))
+bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),5),2),weak(0))
+bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),5),3),weak(0))
+bind_scope_decision(0,dependency(specialization(fnOut,6),2),weak(0))
+bind_scope_decision(0,dependency(specialization(fnOut,6),3),weak(0))
+bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),4),2),weak(1))
+bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),4),3),weak(1))
+bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),5),2),weak(1))
+bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),5),3),weak(1))
+bind_scope_decision(1,dependency(specialization(fnOut,6),2),weak(1))
+bind_scope_decision(1,dependency(specialization(fnOut,6),3),weak(1))
+bind_scope_decision(2,dependency(specialization(fnOut,6),4),resolution_dependency(weak(2,weak(0)),weak(0)))
+bind_scope_decision(2,dependency(specialization(fnOut,6),4),resolution_dependency(weak(2,weak(1)),weak(1)))
+bind_scope_decision(2,dependency(specialization(fnOut,6),5),resolution_dependency(weak(2,weak(0)),weak(0)))
+bind_scope_decision(2,dependency(specialization(fnOut,6),5),resolution_dependency(weak(2,weak(1)),weak(1)))
+bind_scope_decision(3,dependency(specialization(fnOut,6),4),resolution_dependency(weak(3,weak(0)),weak(0)))
+bind_scope_decision(3,dependency(specialization(fnOut,6),4),resolution_dependency(weak(3,weak(1)),weak(1)))
+bind_scope_decision(3,dependency(specialization(fnOut,6),5),resolution_dependency(weak(3,weak(0)),weak(0)))
+bind_scope_decision(3,dependency(specialization(fnOut,6),5),resolution_dependency(weak(3,weak(1)),weak(1)))
+bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyA1A2A3),weak(2,weak(0))))
+bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyA1B2A3),weak(3,weak(0))))
+bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyB1A2A3),weak(2,weak(1))))
+bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyB1B2A3),weak(3,weak(1))))
+bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyA1A2B3),weak(2,weak(0))))
+bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyA1B2B3),weak(3,weak(0))))
+bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyB1A2B3),weak(2,weak(1))))
+bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyB1B2B3),weak(3,weak(1))))
+
+scope_dependencies(dependency(dependency(specialization(fnOut,6),4),2),weak(0))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),4),2),weak(1))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),4),3),weak(0))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),4),3),weak(1))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),5),2),weak(0))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),5),2),weak(1))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),5),3),weak(0))
+scope_dependencies(dependency(dependency(specialization(fnOut,6),5),3),weak(1))
+scope_dependencies(dependency(specialization(fnOut,6),2),weak(0))
+scope_dependencies(dependency(specialization(fnOut,6),2),weak(1))
+scope_dependencies(dependency(specialization(fnOut,6),3),weak(0))
+scope_dependencies(dependency(specialization(fnOut,6),3),weak(1))
+scope_dependencies(dependency(specialization(fnOut,6),4),weak(2,weak(0)))
+scope_dependencies(dependency(specialization(fnOut,6),4),weak(2,weak(1)))
+scope_dependencies(dependency(specialization(fnOut,6),4),weak(3,weak(0)))
+scope_dependencies(dependency(specialization(fnOut,6),4),weak(3,weak(1)))
+scope_dependencies(dependency(specialization(fnOut,6),5),weak(2,weak(0)))
+scope_dependencies(dependency(specialization(fnOut,6),5),weak(2,weak(1)))
+scope_dependencies(dependency(specialization(fnOut,6),5),weak(3,weak(0)))
+scope_dependencies(dependency(specialization(fnOut,6),5),weak(3,weak(1)))
+
+bind_scope(0,keys(keyA1),strong)
+bind_scope(1,keys(keyB1),strong)
+bind_scope(2,keys(keyA1),weak(0))
+bind_scope(2,keys(keyA1A2),weak(0))
+bind_scope(2,keys(keyB1),weak(1))
+bind_scope(2,keys(keyB1A2),weak(1))
+bind_scope(3,keys(keyA1),weak(0))
+bind_scope(3,keys(keyA1B2),weak(0))
+bind_scope(3,keys(keyB1),weak(1))
+bind_scope(3,keys(keyB1B2),weak(1))
+bind_scope(4,keys(keyA1),weak(0))
+bind_scope(4,keys(keyA1A2),weak(2,weak(0)))
+bind_scope(4,keys(keyA1A2A3),weak(2,weak(0)))
+bind_scope(4,keys(keyA1B2),weak(3,weak(0)))
+bind_scope(4,keys(keyA1B2A3),weak(3,weak(0)))
+bind_scope(4,keys(keyB1),weak(1))
+bind_scope(4,keys(keyB1A2),weak(2,weak(1)))
+bind_scope(4,keys(keyB1A2A3),weak(2,weak(1)))
+bind_scope(4,keys(keyB1B2),weak(3,weak(1)))
+bind_scope(4,keys(keyB1B2A3),weak(3,weak(1)))
+bind_scope(5,keys(keyA1),weak(0))
+bind_scope(5,keys(keyA1A2),weak(2,weak(0)))
+bind_scope(5,keys(keyA1A2B3),weak(2,weak(0)))
+bind_scope(5,keys(keyA1B2),weak(3,weak(0)))
+bind_scope(5,keys(keyA1B2B3),weak(3,weak(0)))
+bind_scope(5,keys(keyB1),weak(1))
+bind_scope(5,keys(keyB1A2),weak(2,weak(1)))
+bind_scope(5,keys(keyB1A2B3),weak(2,weak(1)))
+bind_scope(5,keys(keyB1B2),weak(3,weak(1)))
+bind_scope(5,keys(keyB1B2B3),weak(3,weak(1)))
+bind_scope(6,keys(keyA1),weak(0))
+bind_scope(6,keys(keyA1A2),weak(2,weak(0)))
+bind_scope(6,keys(keyA1A2A3),weak(4,weak(2,weak(0))))
+bind_scope(6,keys(keyA1A2B3),weak(5,weak(2,weak(0))))
+bind_scope(6,keys(keyA1B2),weak(3,weak(0)))
+bind_scope(6,keys(keyA1B2A3),weak(4,weak(3,weak(0))))
+bind_scope(6,keys(keyA1B2B3),weak(5,weak(3,weak(0))))
+bind_scope(6,keys(keyB1),weak(1))
+bind_scope(6,keys(keyB1A2),weak(2,weak(1)))
+bind_scope(6,keys(keyB1A2A3),weak(4,weak(2,weak(1))))
+bind_scope(6,keys(keyB1A2B3),weak(5,weak(2,weak(1))))
+bind_scope(6,keys(keyB1B2),weak(3,weak(1)))
+bind_scope(6,keys(keyB1B2A3),weak(4,weak(3,weak(1))))
+bind_scope(6,keys(keyB1B2B3),weak(5,weak(3,weak(1))))
+bind_scope(7,keys(keyA1),weak(0))
+bind_scope(7,keys(keyA1A2),weak(2,weak(0)))
+bind_scope(7,keys(keyA1A2A3),weak(4,weak(2,weak(0))))
+bind_scope(7,keys(keyA1A2B3),weak(5,weak(2,weak(0))))
+bind_scope(7,keys(keyA1B2),weak(3,weak(0)))
+bind_scope(7,keys(keyA1B2A3),weak(4,weak(3,weak(0))))
+bind_scope(7,keys(keyA1B2B3),weak(5,weak(3,weak(0))))
+bind_scope(7,keys(keyB1),weak(1))
+bind_scope(7,keys(keyB1A2),weak(2,weak(1)))
+bind_scope(7,keys(keyB1A2A3),weak(4,weak(2,weak(1))))
+bind_scope(7,keys(keyB1A2B3),weak(5,weak(2,weak(1))))
+bind_scope(7,keys(keyB1B2),weak(3,weak(1)))
+bind_scope(7,keys(keyB1B2A3),weak(4,weak(3,weak(1))))
+bind_scope(7,keys(keyB1B2B3),weak(5,weak(3,weak(1))))
+
+
+
+
+cfa_call(0,a2)
+cfa_call(0,b2)
+cfa_call(1,a2)
+cfa_call(1,b2)
+cfa_call(2,a3)
+cfa_call(2,b3)
+cfa_call(3,a3)
+cfa_call(3,b3)
+cfa_call(4,sink)
+cfa_call(5,sink)
+cfa_call(6,fnOut)
+cfa_function_specializations(fnOut,keys(keyA1A2A3))
+cfa_function_specializations(fnOut,keys(keyA1A2B3))
+cfa_function_specializations(fnOut,keys(keyA1B2A3))
+cfa_function_specializations(fnOut,keys(keyA1B2B3))
+cfa_function_specializations(fnOut,keys(keyB1A2A3))
+cfa_function_specializations(fnOut,keys(keyB1A2B3))
+cfa_function_specializations(fnOut,keys(keyB1B2A3))
+cfa_function_specializations(fnOut,keys(keyB1B2B3))
+cfa_parent(0,function(a1))
+cfa_parent(1,function(b1))
+cfa_parent(2,function(a2))
+cfa_parent(3,function(b2))
+cfa_parent(4,function(a3))
+cfa_parent(5,function(b3))
+cfa_parent(6,function(sink))
+cfa_parent(7,function(fnOut))
+function(a1)
+function(a2)
+function(a3)
+function(b1)
+function(b2)
+function(b3)
+function(fnOut)
+function(sink)
+keys(keyA1)
+keys(keyA1A2)
+keys(keyA1A2A3)
+keys(keyA1A2B3)
+keys(keyA1B2)
+keys(keyA1B2A3)
+keys(keyA1B2B3)
+keys(keyB1)
+keys(keyB1A2)
+keys(keyB1A2A3)
+keys(keyB1A2B3)
+keys(keyB1B2)
+keys(keyB1B2A3)
+keys(keyB1B2B3)
+scope(0)
+scope(1)
+scope(2)
+scope(3)
+scope(4)
+scope(5)
+scope(6)
+scope(7)
+
+true
\ No newline at end of file
diff --git a/scripts/sprint1_environment/tests1-context-latecontext3.lp b/scripts/sprint1_environment/tests1-context-latecontext3.lp
new file mode 120000
index 0000000..c21293f
--- /dev/null
+++ b/scripts/sprint1_environment/tests1-context-latecontext3.lp
@@ -0,0 +1 @@
+/private/prg/code/xreate/scripts/metatests/tests1-context-latecontext3.lp
\ No newline at end of file

Event Timeline