No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:44 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/config/default.json b/config/default.json
index c5f1fcf..f551dc0 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,75 +1,36 @@
{
- "containers": {
- "id": {
- "implementations": "containers_impl",
- "linkedlist": "linkedlist"
- },
-
- "impl": {
- "solid": "solid",
- "onthefly": "onthefly"
- }
- },
+ "template": "problems",
+
+ "templates": {
+ "bugs":"Containers.DONE_ArrayUpdate1",
- "logging": {
- "id": "logging"
- },
-
- "function-entry": "entry",
-
- "transcend": {
- "bindings" : {
- "variable": "bind",
- "function": "bind_func",
- "scope": "bind_scope",
- "function_demand" : "bind_function_demand",
- "scope_decision": "bind_scope_decision"
- },
-
- "context" : {
- "decisions":{
- "dependent": "resolution_dependency"
- }
- },
-
- "nonevalue": "nonevalue",
- "ret": {
- "symbol": "retv",
- "tag": "ret"
- }
- },
-
- "tests": {
- "template": "default",
-
- "templates": {
- "troubleshooting":"*",
- "documentation":"Modules.Doc_*:Modules_API.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*:Introduction.*",
- "default": "*",
- "universal": "Universal.*",
- "ast": "AST.*",
- "effects": "Effects.*",
- "basic": "Attachments.*",
- "compilation": "Compilation.*",
- "communication": "Communication.*",
- "cfa": "CFA.*",
- "containers": "Containers.*",
- "dfa": "DFA.*",
- "diagnostic": "Diagnostic.*",
- "dsl": "Association.*:Interpretation.*",
- "exploitation": "Exploitation.*",
- "ExpressionSerializer": "ExpressionSerializer.*",
- "externc": "InterfaceExternC.*",
- "loops": "Loop.*",
- "latereasoning": "LateReasoning.*",
- "latex": "Latex.*",
- "modules": "Modules.*",
- "polymorphs": "Polymorphs.*",
- "intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*",
- "types": "Types.*",
- "virtualization": "Virtualization.*",
- "vendorsAPI/clang": "ClangAPI.*",
- "vendorsAPI/xml2": "libxml2.*"
- }
- }
+ "default": "*-Colevels.*:Interpretation.*",
+ "documentation":"Modules.Doc_*:Modules_API.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*:Introduction.*",
+ "ast": "AST.*",
+ "effects": "Effects.*",
+ "basic": "Attachments.*",
+ "dimensions": "Dimensions.CompileDeepAnn1",
+ "compilation": "Compilation.*",
+ "communication": "Communication.*",
+ "cfa": "CFA.*",
+ "containers": "Containers.DONE_*",
+ "dfa": "DFA.*",
+ "diagnostic": "Diagnostic.*",
+ "dsl": "Interpretation.*:Association.*",
+ "exploitation": "Exploitation.*",
+ "ExpressionSerializer": "ExpressionSerializer.*",
+ "externc": "InterfaceExternC.*",
+ "loops": "Loop.*",
+ "latereasoning": "LateReasoning.*",
+ "latex": "Latex.*",
+ "modules": "Modules.*",
+ "polymorphs": "PDT.BuildDTTable1",
+ "problems": "Problems.MinMax1",
+ "intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*",
+ "types": "Types.*",
+ "universal": "Universal.*",
+ "virtualization": "Virtualization.*",
+ "vendorsAPI/clang": "ClangAPI.*",
+ "vendorsAPI/xml2": "libxml2.*"
+ }
}
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index d1084db..dd46244 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,34 +1,32 @@
project(Xreate)
cmake_minimum_required(VERSION 2.8.11)
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -fprofile-arcs -ftest-coverage -O0")
-set(CMAKE_BUILD_TYPE Debug)
+include (Configurations.cmake)
+
# BUILD OPTIONS
#======================
-set(XREATE_DEFINITIONS
- -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DWITH_THREADS=1
-)
+set(CMAKE_BUILD_TYPE Debug)
add_definitions(${XREATE_DEFINITIONS})
add_compile_options(-Winvalid-pch -fPIC -std=c++14)
# XREATE
#======================
add_subdirectory(src)
# XREATE-TESTS
#======================
if (BUILD_XREATE_TESTS)
message ("Building xreate tests")
add_subdirectory(tests)
endif ()
# XREATE-SERVER
#======================
if (BUILD_XREATE_SERVER)
message ("Building xreate server")
add_subdirectory(../tools/execution-server execution-server)
endif ()
diff --git a/cpp/Configurations.cmake b/cpp/Configurations.cmake
new file mode 100644
index 0000000..df7021e
--- /dev/null
+++ b/cpp/Configurations.cmake
@@ -0,0 +1,157 @@
+cmake_minimum_required(VERSION 2.8.11)
+
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -fprofile-arcs -ftest-coverage -O0")
+
+
+set(XREATE_DEFINITIONS_COMMON
+ -D_GNU_SOURCE
+ -D__STDC_CONSTANT_MACROS
+ -D__STDC_FORMAT_MACROS
+ -D__STDC_LIMIT_MACROS
+ -DWITH_THREADS=1
+)
+#------------------------------------------------------
+# CONFIGURATION: Min
+
+set(XREATE_SOURCE_FILES_MIN
+ analysis/typeinference.cpp
+ xreatemanager.cpp
+ transcendlayer.cpp
+ llvmlayer.cpp
+ pass/compilepass.cpp
+ analysis/utils.cpp
+ ast.cpp
+ aux/xreatemanager-decorators.cpp
+ compilation/transformations.cpp
+ compilation/transformersaturation.cpp
+ attachments.cpp
+ compilation/control.cpp
+ utils.cpp
+ pass/abstractpass.cpp
+ aux/serialization/expressionserializer.cpp
+ analysis/transcendtarget.cpp analysis/resources.cpp
+ query/containers.cpp
+ modules.cpp
+ compilation/containers.cpp
+ compilation/containers/arrays.cpp
+)
+
+set(XREATE_TEST_FILES_MIN
+ universal.cpp
+ introduction.cpp
+ unit-test-example.cpp
+ supplemental/docutils
+ transcend.cpp
+ association.cpp
+ main.cpp
+ attachments.cpp
+ ast.cpp
+ compilation.cpp
+ ExpressionSerializer.cpp
+ types.cpp
+ #vendorsAPI/clangAPI.cpp
+ #vendorsAPI/xml2.cpp
+ #vendorsAPI/json.cpp
+ loops.cpp
+ #supplemental/versions-algorithm-data_dependency.cpp
+ supplemental/basics.cpp
+)
+
+IF(XREATE_CONFIG STREQUAL "Min")
+ set(XREATE_SOURCE_FILES
+ ${XREATE_SOURCE_FILES_MIN}
+ )
+
+ set(XREATE_TEST_FILES ${XREATE_TEST_FILES_MIN})
+
+ set(XREATE_DEFINITIONS ${XREATE_DEFINITIONS_COMMON}
+ -DXREATE_CONFIG_MIN
+ )
+ENDIF()
+
+#------------------------------------------------------
+# CONFIGURATION: Default
+
+set(XREATE_SOURCE_FILES_DEFAULT ${XREATE_SOURCE_FILES_MIN}
+ compilation/targetinterpretation.cpp
+ analysis/temporalseqgraph.cpp
+ pass/cfatemporalseqpass.cpp
+ analysis/cfagraph.cpp
+ pass/cfapass.cpp
+ compilation/interpretation-instructions.cpp
+ ExternLayer.cpp
+ analysis/cfagraph.cpp
+ compilation/latetranscend.cpp
+ query/latex.cpp
+ aux/latereasoning.cpp
+ analysis/dfagraph.cpp
+ pass/dfapass.cpp
+ pass/interpretationpass.cpp
+ pass/versionspass.cpp
+ contextrule.cpp
+ compilation/demand.cpp
+ analysis/predefinedanns.cpp
+)
+
+set(XREATE_TEST_FILES_DEFAULT ${XREATE_TEST_FILES_MIN}
+ interpretation.cpp
+ transcend-ast.cpp
+ cfa.cpp
+ latetranscend.cpp
+ latex.cpp
+ polymorph.cpp
+ virtualization.cpp
+ exploitation.cpp
+ effects-communication.cpp
+ modules.cpp
+ dfa.cpp
+ effects-versions.cpp
+ containers.cpp
+ externc.cpp
+ aux/expressions.cpp
+ polymorphism-dt.cpp
+)
+
+IF(XREATE_CONFIG STREQUAL "Default")
+ set(XREATE_SOURCE_FILES
+ ${XREATE_SOURCE_FILES_DEFAULT}
+ )
+
+ set(XREATE_TEST_FILES ${XREATE_TEST_FILES_DEFAULT})
+
+ set(XREATE_DEFINITIONS ${XREATE_DEFINITIONS_COMMON}
+ XREATE_ENABLE_EXTERN
+ )
+ENDIF()
+
+#------------------------------------------------------
+# CONFIGURATION: Dimensions
+
+IF(XREATE_CONFIG STREQUAL "Dimensions")
+ set(XREATE_SOURCE_FILES ${XREATE_SOURCE_FILES_MIN}
+ query/demand.cpp
+ compilation/demand.cpp
+ query/polymorph.cpp
+ compilation/polymorph.cpp
+ aux/expressions.cpp
+ pass/interpretationpass.cpp
+ compilation/targetinterpretation.cpp
+ compilation/intrinsics.cpp
+# compilation/containerinst.cpp
+ analysis/predefinedanns.cpp
+ analysis/typehints.cpp
+ )
+
+ set(XREATE_TEST_FILES ${XREATE_TEST_FILES_MIN}
+ interpretation.cpp
+ dimensions.cpp
+ polymorph.cpp
+ polymorphism-dt.cpp
+ containers.cpp
+ problems.cpp
+ )
+
+ set(XREATE_DEFINITIONS ${XREATE_DEFINITIONS_COMMON}
+ -DXREATE_CONFIG_MIN
+ )
+ENDIF()
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index ff23a2c..2b91e83 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,247 +1,197 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Native arch: ${LLVM_NATIVE_ARCH}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
message(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS})
execute_process(
COMMAND llvm-config --libs
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# POTASSCO
#======================
set(CLINGO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${CLINGO_PATH}/libgringo
${CLINGO_PATH}/libclasp
${CLINGO_PATH}/libclingo
${CLINGO_PATH}/libprogram_opts
${CLINGO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
-
-# OTHER DEPENDENCIES
-#===========================
-set(JEAYESON_INCLUDE_PATH
- ${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
-)
-INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
-
-
-
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/)
set(COCO_SOURCE_FILES_MAIN
${COCO_GRAMMAR_PATH}/main/Parser.cpp
${COCO_GRAMMAR_PATH}/main/Scanner.cpp
)
set(COCO_SOURCE_FILES_MODULES
${COCO_GRAMMAR_PATH}/modules/Parser.cpp
${COCO_GRAMMAR_PATH}/modules/Scanner.cpp
)
set(COCO_SOURCE_FILES_UNIVERSAL
${COCO_GRAMMAR_PATH}/universal/Parser.cpp
${COCO_GRAMMAR_PATH}/universal/Scanner.cpp
)
set(COCO_SOURCE_FILES
${COCO_SOURCE_FILES_MODULES}
${COCO_SOURCE_FILES_MAIN}
${COCO_SOURCE_FILES_UNIVERSAL}
)
INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH})
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MAIN}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar main ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG
)
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MODULES}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar modules ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/modules.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
-set(SOURCE_FILES
- analysis/temporalseqgraph.cpp
- pass/cfatemporalseqpass.cpp
- analysis/cfagraph.cpp
- pass/cfapass.cpp
- modules.cpp
- compilation/interpretation-instructions.cpp
- ExternLayer.cpp
- analysis/cfagraph.cpp
- compilation/latetranscend.cpp
- analysis/interpretation.cpp
- query/latex.cpp
- query/polymorph.cpp
- compilation/polymorph.cpp
- aux/latereasoning.cpp
- compilation/latex.cpp
- analysis/typeinference.cpp
- xreatemanager.cpp
- transcendlayer.cpp
- analysis/dfagraph.cpp
- llvmlayer.cpp
- pass/compilepass.cpp
- analysis/utils.cpp
- pass/dfapass.cpp
- compilation/targetinterpretation.cpp
- pass/interpretationpass.cpp
- ast.cpp
- aux/xreatemanager-decorators.cpp
- compilation/operators.cpp
- compilation/transformations.cpp
- compilation/transformersaturation.cpp
- pass/versionspass.cpp
- attachments.cpp
- compilation/containers.cpp
- compilation/advancedinstructions.cpp
- utils.cpp
- pass/abstractpass.cpp
- contextrule.cpp
- query/containers.cpp
- aux/serialization/expressionserializer.cpp
-)
+
+#source files defined in configuration.cmake
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
- ${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
-add_library(${PROJECT_NAME} SHARED ${COCO_SOURCE_FILES} ${SOURCE_FILES})
+add_library(${PROJECT_NAME} SHARED ${COCO_SOURCE_FILES} ${XREATE_SOURCE_FILES})
target_link_libraries(${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
- ${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
message("definitions all: " ${DEFINITIONS_ALL})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL})
get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
message("compilations all: " ${COMPILATION_OPTIONS_ALL})
target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL})
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY
INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb boost_system boost_filesystem
)
#${CLANG_LIBS}
#set (LINK_INTERFACE_LIBRARIES "")
# FUNCTION(PREPEND var prefix)
# SET(listVar "")
# FOREACH(f ${ARGN})
# LIST(APPEND listVar "${prefix}/${f}")
# ENDFOREACH(f)
# SET(${var} "${listVar}" PARENT_SCOPE)
# ENDFUNCTION(PREPEND)
#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
#cotire(xreate)
# MACRO (ADD_PCH_RULE _header_filename _src_list)
# SET(_gch_filename "${_header_filename}.gch")
# LIST(APPEND ${_src_list} ${_gch_filename})
# SET (_args ${CMAKE_CXX_FLAGS})
# LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename})
# GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
# foreach (_inc ${DIRINC})
# LIST(APPEND _args "-I" ${_inc})
# endforeach(_inc ${DIRINC})
# SEPARATE_ARGUMENTS(_args)
# add_custom_command(OUTPUT ${_gch_filename}
# COMMAND rm -f ${_gch_filename}
# COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
# DEPENDS ${_header_filename})
# ENDMACRO(ADD_PCH_RULE _header_filename _src_list)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 03afa74..247f833 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,334 +1,321 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ExternLayer.cpp
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "ExternLayer.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <cstdio>
#include <iostream>
#include <clang/Frontend/CompilerInstance.h>
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
namespace xreate{
class FinderCallbackTypeDecl : public MatchFinder::MatchCallback{
public:
QualType typeResult;
virtual void
run(const MatchFinder::MatchResult &Result) {
if (const TypedefDecl * decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
typeResult = decl->getUnderlyingType();
}
}
} ;
class FinderCallbackFunction : public MatchFinder::MatchCallback{
public:
QualType typeResult;
virtual void
run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl * decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
typeResult = decl->getType();
}
}
} ;
void
-ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package) {
- __dictLibraries.emplace(name.get(), package.get());
+ExternData::addLibAlias(Atom<Identifier_t>&& alias, std::string&& package) {
+ __aliases.emplace(alias.get(), package.get());
}
void
-ExternData::addIncludeDecl(Expression&& e) {
- assert(e.op == Operator::LIST);
-
- //TODO ?? implement Expression parsing(Array of Expr as vector<string>);
- for(size_t i = 0, size = e.operands.size(); i < size; ++i) {
- std::string library = e.bindings.at(i);
- assert(__dictLibraries.count(library));
- std::string package = __dictLibraries.at(library);
-
- Expression listHeaders = e.operands.at(i);
- assert(listHeaders.op == Operator::LIST);
-
- std::vector<std::string> headers;
- std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
- [](const Expression & o) {
- assert(o.__state == Expression::STRING);
- return o.getValueString();
- });
-
- entries.emplace_back(ExternEntry{package, std::move(headers)});
- }
+ExternData::requireHeaders(const std::list<std::string>& headers){
+ __requiredHeaders.insert(
+ std::inserter(__requiredHeaders, __requiredHeaders.end()),
+ headers.begin(), headers.end());
+}
+
+void
+ExternData::requireLibPackage(Atom<String_t>&& package){
+ __requiredPackages.push_back(package.get());
+}
+
+void
+ExternData::requireLibAlias(Atom<Identifier_t>&& alias){
+ assert(__aliases.count(alias.get());
+ __requiredPackages.push_back(__aliases.at(alias.get()));
}
void
ExternLayer::addExternalData(const std::vector<ExternEntry>& data) {
entries.insert(entries.end(), data.begin(), data.end());
}
ExternLayer::ExternLayer(LLVMLayer *llvm)
: __llvm(llvm) { }
std::vector<string>
-ExternLayer::fetchPackageFlags(const ExternEntry& entry) {
+ExternLayer::fetchPackageFlags(const std::string& package) {
std::vector<string> args;
- FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
+ FILE* flags = popen((string("pkg-config --cflags ") + package).c_str(), "r");
size_t linesize = 0;
char* linebuf = 0;
ssize_t linelen = 0;
while ((linelen = getdelim(&linebuf, &linesize, ' ', flags)) > 0) {
if (linebuf[0] == '\n') continue;
if (linelen == 1 && linebuf[0] == ' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen - 1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen - 1] = 0;
//print header for debug purposes
llvm::outs() << '<' << linebuf << "> ";
args.push_back(linebuf);
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (args);
}
std::vector<string>
-ExternLayer::fetchPackageLibs(const ExternEntry& entry) {
+ExternLayer::fetchPackageLibs(const std::string& package) {
std::vector<string> libs;
- FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
+ FILE* flags = popen((string("pkg-config --libs ") + package).c_str(), "r");
size_t linesize = 0;
char* linebuf = 0;
ssize_t linelen = 0;
while ((linelen = getdelim(&linebuf, &linesize, ' ', flags)) > 0) {
if (linebuf[0] == '\n') continue;
if (linelen == 1 && linebuf[0] == ' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen - 1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen - 1] = 0;
//cut unwanted symbols at the beginning
if (linelen > 1 && linebuf[0] == '-' && linebuf[1] == 'l') {
libs.push_back(linebuf + 2);
} else {
libs.push_back(linebuf);
}
//print lib name for debug purposes
llvm::outs() << '<' << linebuf << "> ";
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (libs);
}
void
ExternLayer::loadLibraries(vector<string>&& libs) {
string msgErr;
for (const string& lib : libs) {
const string& libName = string("lib") + lib + ".so";
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(libName.c_str(), &msgErr)) {
llvm::errs() << "\n" << "Loading library " << lib << ". " << msgErr << "\n";
}
}
}
void
-ExternLayer::init(const AST* root) {
- addExternalData(root->__externdata);
-
- // TODO -EXTERN01.DIP, use default include path from 'clang -xc++ -E'
- list<string> code;
- std::vector<string> args{
- "-I/usr/include"
- , "-I/usr/local/include"
- , "-I/usr/lib64/clang/5.0.1/include"
- // ,"-I/usr/lib/gcc/x86_64-linux-gnu/4.9/include"
- // ,"-I/usr/include/x86_64-linux-gnu"
- };
-
- std::vector<string> libs;
-
- boost::format formatInclude("#include \"%1%\"");
- for(const ExternEntry& entry : entries) {
- llvm::outs() << "[ExternC] Processing package: " << entry.package << "\n";
- llvm::outs() << "[ExternC] args: ";
-
- vector<string>&& args2 = fetchPackageFlags(entry);
- args.insert(args.end(), args2.begin(), args2.end());
- for(const string arg : args2) {
- llvm::outs() << "<" << arg << "> ";
- }
-
- llvm::outs() << "\n[ExternC] libs: ";
- args2 = fetchPackageLibs(entry);
- for(const string arg : args2) {
- llvm::outs() << "<" << arg << "> ";
- }
- libs.insert(libs.end(), args2.begin(), args2.end());
-
-
- llvm::outs() << "\n[ExternC] headers: ";
- std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
- [&formatInclude](const string header ) {
- string line = boost::str(formatInclude % header);
- llvm::outs() << "<" << line << "> ";
-
- return line;
- });
-
- llvm::outs() << '\n';
- }
-
- loadLibraries(move(libs));
- ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
- __llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayout());
- __clang.reset(new CompilerInstance());
- __clang->createDiagnostics();
-
- __codegen.reset(CreateLLVMCodeGen(
- __clang->getDiagnostics(),
- __llvm->module->getName(),
- __clang->getHeaderSearchOpts(),
- __clang->getPreprocessorOpts(),
- clang::CodeGenOptions(),
- __llvm->llvmContext
- ));
-
- __codegen->Initialize(ast->getASTContext());
+ExternLayer::init(const AST* ast) {
+ std::vector<string> args{
+ "-isystem"
+ };
+
+ list<string> code;
+ std::vector<string> libs;
+
+ boost::format formatInclude("#include \"%1%\"");
+ for(const ExternData& entry : ast->__externdata) {
+ llvm::outs() << "[ExternC] Processing package: " << entry.package << "\n";
+ llvm::outs() << "[ExternC] args: ";
+
+ vector<string>&& args2 = fetchPackageFlags(entry);
+ args.insert(args.end(), args2.begin(), args2.end());
+ for(const string arg : args2) {
+ llvm::outs() << "<" << arg << "> ";
+ }
+
+ llvm::outs() << "\n[ExternC] libs: ";
+ args2 = fetchPackageLibs(entry);
+ for(const string arg : args2) {
+ llvm::outs() << "<" << arg << "> ";
+ }
+ libs.insert(libs.end(), args2.begin(), args2.end());
+
+
+ llvm::outs() << "\n[ExternC] headers: ";
+ std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
+ [&formatInclude](const string header ) {
+ string line = boost::str(formatInclude % header);
+ llvm::outs() << "<" << line << "> ";
+
+ return line;
+ });
+
+ llvm::outs() << '\n';
+ }
+
+ loadLibraries(move(libs));
+ ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
+ __llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayout());
+ __clang.reset(new CompilerInstance());
+ __clang->createDiagnostics();
+
+ __codegen.reset(CreateLLVMCodeGen(
+ __clang->getDiagnostics(),
+ __llvm->module->getName(),
+ __clang->getHeaderSearchOpts(),
+ __clang->getPreprocessorOpts(),
+ clang::CodeGenOptions(),
+ __llvm->llvmContext
+ ));
+
+ __codegen->Initialize(ast->getASTContext());
};
bool
ExternLayer::isPointer(const clang::QualType &t) {
const clang::Type * tInfo = t.getTypePtr();
assert(tInfo);
return tInfo->isAnyPointerType();
}
llvm::Type*
ExternLayer::toLLVMType(const clang::QualType& t) {
return CodeGen::convertTypeForMemory( __codegen->CGM(), t);
}
std::vector<std::string>
ExternLayer::getStructFields(const clang::QualType& ty) {
clang::QualType t = ty;
if (isPointer(ty)) {
const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
t = tPtr->getPointeeType();
}
assert(t.getTypePtr()->isRecordType());
const RecordType *record = t->getAsStructureType();
assert(record);
std::vector<std::string> result;
//FieldDecl* field: record->getDecl()->fields()
for (auto i = record->getDecl()->field_begin(); i != record->getDecl()->field_end(); ++i) {
result.push_back(i->getName());
}
return result;
}
bool
ExternLayer::isArrayType(const std::string& type){
clang::QualType typeRaw = lookupType(type);
if (isPointer(typeRaw)) {
const clang::PointerType* typePtr = typeRaw->getAs<clang::PointerType>();
typeRaw = typePtr->getPointeeType();
}
return typeRaw->isArrayType();
}
bool
ExternLayer::isRecordType(const std::string& type){
clang::QualType typeRaw = lookupType(type);
if (isPointer(typeRaw)) {
const clang::PointerType* typePtr = typeRaw->getAs<clang::PointerType>();
typeRaw = typePtr->getPointeeType();
}
return typeRaw->isRecordType();
}
clang::QualType
ExternLayer::lookupType(const std::string& id) {
MatchFinder finder;
FinderCallbackTypeDecl callbackTypeDecl;
auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
finder.matchAST(ast->getASTContext());
assert(! callbackTypeDecl.typeResult.isNull());
return callbackTypeDecl.typeResult;
}
llvm::Function*
ExternLayer::lookupFunction(const std::string& name) {
if (__functions.count(name)) {
return __functions.at(name);
}
MatchFinder finder;
FinderCallbackFunction callback;
auto matcher = functionDecl(hasName(name)).bind("function");
finder.addMatcher(matcher, &callback);
finder.matchAST(ast->getASTContext());
if (callback.typeResult.isNull()) {
cout << "[External Layer] " << "Unknown function: " << name << endl;
assert(false && "Unknown external function");
}
const QualType& tyFuncQual = callback.typeResult;
llvm::Type *tyRaw = CodeGen::convertTypeForMemory(__codegen->CGM(), tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
llvm::Function* function = llvm::Function::Create(
tyRawFunc,
llvm::GlobalValue::ExternalLinkage,
name,
__llvm->module.get());
__functions.emplace(name, function);
return function;
}
}//end of xreate namespace
diff --git a/cpp/src/ExternLayer.h b/cpp/src/ExternLayer.h
index 0bae75e..2a0a976 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,72 +1,62 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ExternLayer.h
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file ExternLayer.h
* \brief An external C code interaction support
*/
#ifndef XREATE_EXTERNLAYER_H
#define XREATE_EXTERNLAYER_H
#include "llvmlayer.h"
#include <vector>
#include <string>
#include <map>
#include "ast.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "clang/Lex/PreprocessorOptions.h"
namespace clang{
class CodeGenerator;
}
namespace xreate{
-struct ExternData{
- void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
- void addIncludeDecl(Expression&& e);
-
- std::vector<ExternEntry> entries;
- std::map<std::string, std::string> __dictLibraries;
-};
-
/** \brief A wrapper over Clang */
class ExternLayer{
public:
ExternLayer(LLVMLayer* llvm);
- void init(const AST* root);
+ void init(const AST* ast);
llvm::Function* lookupFunction(const std::string& name);
clang::QualType lookupType(const std::string& id);
std::vector<std::string> getStructFields(const clang::QualType& ty);
llvm::Type* toLLVMType(const clang::QualType& t);
bool isPointer(const clang::QualType& t);
bool isArrayType(const std::string& type);
bool isRecordType(const std::string& type);
- static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
- static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
+ static std::vector<std::string> fetchPackageFlags(const std::string& package);
+ static std::vector<std::string> fetchPackageLibs(const std::string& package);
private:
std::unique_ptr<clang::ASTUnit> ast;
std::unique_ptr<clang::CodeGenerator> __codegen;
std::unique_ptr<clang::CompilerInstance> __clang;
LLVMLayer* __llvm;
- std::vector<ExternEntry> entries;
std::map<std::string, llvm::Function*> __functions;
- void addExternalData(const std::vector<ExternEntry>& data);
void loadLibraries(std::vector<std::string>&& libs);
};
}
#endif //XREATE_EXTERNLAYER_H
diff --git a/cpp/src/analysis/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp
index 2e24ca2..1716a5d 100644
--- a/cpp/src/analysis/cfagraph.cpp
+++ b/cpp/src/analysis/cfagraph.cpp
@@ -1,181 +1,139 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
/**
* \file cfagraph.h
* \brief Control Flow Analysis(CFA) graph representation
*/
#include "analysis/cfagraph.h"
#include "analysis/utils.h"
using namespace xreate::cfa;
using namespace std;
void
CFAGraph::print(std::ostringstream& output) const {
- const std::string& atomBinding = Config::get("transcend.bindings.function");
const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
output << endl << "%\t\tStatic analysis: CFA" << endl;
output << __outputPrecomputed.str();
- //show function tags
- int counterTags = 0;
- boost::format formatFunction("function(\"%1%\").");
- boost::format formatBind(atomBinding + "(\"%1%\", %2%).");
- for (auto function : this->__fnNodes.left) {
- const auto tags = this->__fnTags.equal_range(function.first);
- 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 (counterTags == 0) {
- output << "%no function tags at all" << endl;
- }
-
//declare scopes
boost::format formatScope("scope(0..%1%).");
output << formatScope % (__transcend->getScopesCount() - 1) << std::endl;
//show context rules:
for (auto rule : this->__contextRules) {
output << ContextRule(rule.second).compile(rule.first) << std::endl;
};
- //show scope tags:
- counterTags = 0;
- boost::format formatScopeBind(atomBindingScope + "(%1%, %2%, strong).");
- for (auto entry : this->__scopeTags) {
- ScopePacked scopeId = entry.first;
- const Expression& tag = entry.second;
- list<string> tagRaw = xreate::analysis::compile(tag);
- assert(tagRaw.size() == 1);
-
- output << formatScopeBind % scopeId % (tagRaw.front()) << endl;
- ++counterTags;
- }
- if (counterTags == 0) {
- output << "%scope tags: no tags at all" << endl;
- }
//parent connections
//TOTEST CFG parent function
boost::format formatFunctionParent("cfa_parent(%1%, function(\"%2%\")).");
for (const auto &relation : this->__parentFnRelation) {
const string& function = this->__fnNodes.left.at(relation.right);
output << formatFunctionParent % relation.left % function << endl;
}
//TOTEST CFG parent scope
boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
for (const auto &relation : this->__parentScopeRelation) {
output << formatScopeParent % relation.first % relation.second << endl;
}
//call connections
boost::format formatCall("cfa_call(%1%, \"%2%\").");
for (const auto &relation : this->__callRelations) {
const ScopePacked scopeFrom = relation.left;
const string& functionTo = this->__fnNodes.left.at(relation.right);
output << formatCall % (scopeFrom) % (functionTo) << endl;
}
//function specializations description
boost::format formatSpecializations("cfa_function_specializations(\"%1%\", %2%).");
const list<ManagedFnPtr>& functions = __transcend->ast->getAllFunctions();
for (auto f : functions) {
if (f->guard.isValid()) {
list<string> guardRaw = xreate::analysis::compile(f->guard);
assert(guardRaw.size() == 1);
output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
}
}
}
void
CFAGraph::addFunctionAnnotations(const std::string& fn, const std::map<std::string, Expression>& tags) {
unsigned int fid = registerNodeFunction(fn);
for (auto& tag : tags) {
__fnTags.emplace(fid, tag.second);
}
}
void
CFAGraph::addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>& tags) {
for (Expression tag : tags) {
__scopeTags.emplace(scope, tag);
}
}
void
CFAGraph::addContextRules(const ScopePacked& scope, const std::vector<Expression>& rules) {
for (Expression rule : rules) {
__contextRules.emplace(scope, rule);
}
}
void
CFAGraph::addCallConnection(const ScopePacked& callerScope, const std::string& calleeFn) {
unsigned int idFuncTo = registerNodeFunction(calleeFn);
__callRelations.insert(CALL_RELATIONS::value_type(callerScope, idFuncTo));
}
void
CFAGraph::addParentConnection(const ScopePacked& scopeEntry, const std::string& fnParent) {
__parentFnRelation.insert(PARENT_FUNCTION_RELATIONS::value_type(scopeEntry, registerNodeFunction(fnParent)));
}
void
CFAGraph::addParentConnection(const ScopePacked& scopeChild, const ScopePacked& scopeParent) {
__parentScopeRelation.emplace(scopeChild, scopeParent);
}
unsigned int
CFAGraph::registerNodeFunction(const std::string& fname) {
auto pos = __fnNodes.left.insert(make_pair(__fnNodes.size(), fname));
return pos.first->first;
}
void
CFAGraph::addScope(CodeScope* scope) {
boost::format formatScopeBinding("ast_scope_binding(%1%, %2%, \"%3%\").");
ScopePacked scopeId = __transcend->pack(scope);
__scopesCount = max(scopeId + 1, __scopesCount);
for (int id = 0, size = scope->__bindings.size(); id < size; ++id) {
__outputPrecomputed << formatScopeBinding
% scopeId
% id
% scope->__bindings.at(id)
<< endl;
}
}
diff --git a/cpp/src/analysis/interpretation.cpp b/cpp/src/analysis/interpretation.cpp
deleted file mode 100644
index 7c18b4e..0000000
--- a/cpp/src/analysis/interpretation.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Author: pgess <v.melnychenko@xreate.org>
- * Created on June 25, 2018, 3:25 PM
- */
-
-#include "analysis/interpretation.h"
-
-using namespace std;
-
-namespace xreate{
-namespace interpretation{
-
-typedef vector<int> InstancePacked;
-
-std::list<Expression>
-generateAllInstancesInDomain2(const ExpandedType& domainT) {
- if(!domainT->isValid()) {
- return {Expression()};
- }
- assert(domainT->__operator == TypeOperator::VARIANT);
- std::list<Expression> results;
- int variantId = -1;
-
- bool flagDomainStateless = std::all_of(domainT->__operands.begin(), domainT->__operands.end(),
- [](const TypeAnnotation & subdomainT) {
- return !subdomainT.isValid();
- });
-
- for(const TypeAnnotation& subdomainT : domainT->__operands) {
- ++variantId;
-
- if(flagDomainStateless) {
- Expression result(Operator::VARIANT,{});
- result.setValueDouble(variantId);
- results.push_back(result);
- continue;
- }
-
- std::list<Expression> subresults = generateAllInstancesInDomain2(ExpandedType(subdomainT));
- for (const Expression& subresult : subresults) {
- Expression result(Operator::VARIANT,{});
- result.setValueDouble(variantId);
- result.operands.push_back(subresult);
-
- results.push_back(result);
- }
- }
-
- return results;
-}
-
-TypeAnnotation
-collapseFnGroup(const std::list<Gringo::Symbol>& symbols) {
- Gringo::Symbol symbolAny = symbols.front();
- size_t operandsCount = symbolAny.args().size;
-
- TypeAnnotation resultT;
- resultT.__operands.reserve(operandsCount);
-
- for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
- std::list<Gringo::Symbol> column;
-
- for(const Gringo::Symbol& row : symbols) {
- column.push_back(row.args()[operandId]);
- }
-
- TypeAnnotation operandT = collapseColumn(column);
- resultT.__operands.push_back(operandT);
- }
-
- if(resultT.__operands.size() == 1) {
- return resultT.__operands.front();
- }
-
- if(resultT.__operands.size() > 1) {
- resultT.__operator = TypeOperator::LIST_RECORD;
- return resultT;
- }
-
- return resultT;
-}
-
-TypeAnnotation
-collapseColumn(const std::list<Gringo::Symbol>& symbols) {
- TypeAnnotation resultT;
- if(!symbols.size()) return resultT;
-
- Gringo::Symbol symbolAny = symbols.front();
-
- switch(symbolAny.type()) {
- case Gringo::SymbolType::Num:
- {
- return TypeAnnotation(TypePrimitive::Num);
- }
-
- case Gringo::SymbolType::Str:
- {
- return TypeAnnotation(TypePrimitive::String);
- }
-
- case Gringo::SymbolType::Fun:
- {
- map<string, list < Gringo::Symbol>> fnGroups;
-
- for(const Gringo::Symbol& row : symbols) {
- fnGroups[row.name().c_str()].push_back(row);
- }
-
- TypeAnnotation resultT;
- resultT.__operands.reserve(fnGroups.size());
- resultT.bindings.reserve(fnGroups.size());
-
- for(const auto& group : fnGroups) {
- if(!group.second.size()) continue;
-
- TypeAnnotation variantT = collapseFnGroup(group.second);
- Gringo::Symbol symbolAny = group.second.front();
- string variantName = symbolAny.name().c_str();
- resultT.fields.push_back(variantName);
- resultT.__operands.push_back(variantT);
- }
-
- resultT.__operator = TypeOperator::VARIANT;
- // if(resultT.__operands.size() == 1) {
- // return resultT.__operands.front();
- // }
- return resultT;
- }
-
- case Gringo::SymbolType::Inf:
- case Gringo::SymbolType::Special:
- case Gringo::SymbolType::Sup:
- {
- break;
- }
- }
-
- assert(false);
- return TypeAnnotation();
-}
-
-ExpandedType
-dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend) {
- assert(t->__operator == TypeOperator::SLAVE);
- const string& domain = t->__valueCustom;
- StaticModel model = transcend->query(domain);
- if(!model.size()) return ExpandedType(TypeAnnotation());
-
- std::list<Gringo::Symbol> symbols;
- for(auto row : model) {
- symbols.push_back(row.second);
- }
- return ExpandedType(collapseFnGroup(symbols));
-}
-
-Expression
-representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend) {
- atom.print(std::cout); std::cout<<endl;
- switch(schemaT->__operator) {
- case TypeOperator::NONE:
- {
- switch(schemaT->__value) {
- case TypePrimitive::I8:
- case TypePrimitive::I32:
- case TypePrimitive::I64:
- case TypePrimitive::Num:
- case TypePrimitive::Int:
- {
- return Expression(Atom<Number_t>(atom.num()));
- }
-
- case TypePrimitive::String:
- {
- return Expression(Atom<String_t>(atom.string().c_str()));
- }
-
- case TypePrimitive::Invalid:
- case TypePrimitive::Bool:
- case TypePrimitive::Float:
- {
- assert(false);
- return Expression();
- }
- }
- break;
- }
-
- case TypeOperator::SLAVE:
- {
- ExpandedType contentT = dereferenceSlaveType(schemaT, transcend);
- return representTransExpression(atom, contentT, transcend);
- }
-
- case TypeOperator::VARIANT:
- {
- map<string, int> dictVariants;
- for(size_t variantId = 0; variantId < schemaT->fields.size(); ++variantId) {
- dictVariants.emplace(schemaT->fields.at(variantId), variantId);
- }
-
- string predicateName = atom.name().c_str();
- assert(dictVariants.count(predicateName));
-
- size_t predicateId = dictVariants.at(predicateName);
- Expression result(Operator::VARIANT,{});
- result.op = Operator::VARIANT;
- result.setValueDouble(predicateId);
-
- if(!schemaT->__operands.size()) return result;
- ExpandedType contentT = schemaT->__operands.at(predicateId).__operator == TypeOperator::SLAVE
- ? dereferenceSlaveType(ExpandedType(schemaT->__operands.at(predicateId)), transcend)
- : ExpandedType(schemaT->__operands.at(predicateId));
-
- //edge case, content's type is LIST_NAMED:
- if (contentT->__operator == TypeOperator::LIST_RECORD) {
- result.operands.push_back(representTransExpression(atom, contentT, transcend));
-
- } else if(!contentT->isValid()) {
- return result;
-
- } else {
- assert(atom.args().size);
- result.operands.push_back(representTransExpression(atom.args()[0], contentT, transcend));
- }
-
- return result;
- }
-
- case TypeOperator::LIST_RECORD:
- {
- const Gringo::SymSpan& operandsRaw = atom.args();
- size_t opCount = operandsRaw.size;
- assert(opCount == schemaT->__operands.size());
-
- size_t operandId = 0;
- std::vector<Expression> operands;
- operands.reserve(opCount);
- for(const TypeAnnotation operandT : schemaT->__operands) {
- operands.push_back(representTransExpression(operandsRaw[operandId], ExpandedType(operandT), transcend));
- ++operandId;
- }
-
- Expression result(Operator::LIST,{});
- result.operands = operands;
- result.type = schemaT;
- return result;
- }
-
- case TypeOperator::LIST_ARRAY:
- case TypeOperator::CALL:
- case TypeOperator::CUSTOM:
- case TypeOperator::ACCESS:
- case TypeOperator::LINK:
- {
- assert(false);
- return Expression();
- }
- }
-
- assert(false);
- return Expression();
-}
-
-}
-} //end of xreate namespace
diff --git a/cpp/src/analysis/interpretation.h b/cpp/src/analysis/interpretation.h
deleted file mode 100644
index 8a93e17..0000000
--- a/cpp/src/analysis/interpretation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Author: pgess <v.melnychenko@xreate.org>
- * Created on June 25, 2018, 3:24 PM
- */
-
-/**
- * \file interpretation.h
- * \brief Interpretation related functions
- */
-
-#ifndef INTERPRETATION_H
-#define INTERPRETATION_H
-
-#include "transcendlayer.h"
-
-namespace xreate{ namespace interpretation{
-
- /**
- * \brief Converts a Transcend's fact to a Xreate's expression that can be interpreted further. Supports `query` keyword.
- * @param atom Transcend's fact
- * @param schemaT Type of the resulting expression
- * @param transcend Transcend's instance
- * @return converted Transcend' fact in form of Xreate's expression
- */
- Expression representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend);
-
- /**
- * \brief Expands slave type.
- * @param t Slave type
- * @param transcend Instance of Transcend
- * @return The expanded slave type
- */
- ExpandedType dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend);
-
- TypeAnnotation collapseColumn(const std::list<Gringo::Symbol>& symbols);
- std::list<Expression> generateAllInstancesInDomain2(const ExpandedType& domainT);
-
-}
-}
-#endif /* INTERPRETATION_H */
-
diff --git a/cpp/src/analysis/predefinedanns.cpp b/cpp/src/analysis/predefinedanns.cpp
new file mode 100644
index 0000000..59812a2
--- /dev/null
+++ b/cpp/src/analysis/predefinedanns.cpp
@@ -0,0 +1,64 @@
+//
+// Created by pgess on 19/03/2020.
+//
+
+#include "analysis/predefinedanns.h"
+
+namespace xreate{ namespace analysis{
+
+PredefinedAnns
+PredefinedAnns::__instance = PredefinedAnns();
+
+PredefinedAnns::PredefinedAnns(){
+ fnAnnsT = TypeAnnotation(TypeOperator::VARIANT, {});
+ exprAnnsT = TypeAnnotation(TypeOperator::VARIANT, {});
+
+ //entry
+ fnAnnsT.__operands.push_back(TypePrimitive::Invalid);
+ fnAnnsT.fields.push_back("entry");
+
+ //interpretation
+ i12nModeT = TypeAnnotation(TypeOperator::VARIANT, {
+ TypePrimitive::Invalid,
+ TypePrimitive::Invalid
+ });
+ i12nModeT.fields.push_back("on");
+ i12nModeT.fields.push_back("off");
+
+ exprAnnsT.__operands.push_back(i12nModeT);
+ exprAnnsT.fields.push_back("i12n");
+
+ //Int
+ hintsIntT = TypeAnnotation(TypeOperator::VARIANT, {
+ TypePrimitive ::Int
+ });
+ hintsIntT.fields.push_back("size");
+
+ //Containers
+ hintsContT = TypeAnnotation(TypeOperator::VARIANT, {
+ TypePrimitive::Int
+ });
+ hintsContT.fields.push_back("csize");
+}
+
+void
+PredefinedAnns::fillRegistry(std::map<std::string, std::pair<TypeAnnotation, int>> &__registry) const{
+ __registry = {
+ //Functions:
+ {"entry", {fnAnnsT, (unsigned) FnAnnotations::ENTRY}},
+
+ //Expressions:
+ {"i12n", {exprAnnsT, (unsigned) ExprAnnotations::I12N}},
+
+ //Interpretation:
+ {"on", {i12nModeT, (unsigned) I12ModeTag::ON}},
+ {"off", {i12nModeT, (unsigned) I12ModeTag::OFF}},
+
+ //Int:
+ {"size", {hintsIntT, (unsigned) IntHints::SIZE}},
+
+ //Containers
+ {"csize", {hintsContT, (unsigned) ContHints::ARRAY}},
+ };
+}
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/predefinedanns.h b/cpp/src/analysis/predefinedanns.h
new file mode 100644
index 0000000..6d16e73
--- /dev/null
+++ b/cpp/src/analysis/predefinedanns.h
@@ -0,0 +1,48 @@
+//
+// Created by pgess on 19/03/2020.
+//
+
+#ifndef XREATE_PREDEFINEDANNS_H
+#define XREATE_PREDEFINEDANNS_H
+
+#include "ast.h"
+
+namespace xreate{ namespace analysis{
+class PredefinedAnns{
+public:
+ enum class FnAnnotations{
+ ENTRY
+ };
+ enum class ExprAnnotations{
+ I12N
+ };
+ enum class I12ModeTag{
+ ON, OFF
+ };
+ enum class IntHints{
+ SIZE
+ };
+
+ enum class ContHints{
+ ARRAY
+ };
+
+ TypeAnnotation fnAnnsT;
+ TypeAnnotation exprAnnsT;
+ TypeAnnotation hintsIntT;
+ TypeAnnotation hintsContT;
+
+ //Interpretation
+ TypeAnnotation i12nModeT;
+
+ PredefinedAnns();
+ static const PredefinedAnns& instance(){ return __instance; }
+ void fillRegistry(std::map<std::string, std::pair<TypeAnnotation, int>> &__registry) const;
+
+private:
+ static PredefinedAnns __instance;
+};
+
+}} // end of xreate::analysis
+
+#endif //XREATE_PREDEFINEDANNS_H
diff --git a/cpp/src/analysis/resources.cpp b/cpp/src/analysis/resources.cpp
new file mode 100644
index 0000000..e80a121
--- /dev/null
+++ b/cpp/src/analysis/resources.cpp
@@ -0,0 +1,24 @@
+#include "analysis/resources.h"
+namespace xreate{namespace analysis{
+
+const char *VAR_ANN_PREDICATE_TPL = "bind(%1%, %2%)";
+const char *VAR_ANN_PREDICATE = "bind";
+const char *SCOPE_ANN_PREDICATE_TPL = "bind_scope(%1%, %2%)";
+const char *SCOPE_ANN_PREDICATE = "bind_scope";
+const char *FUNCTION_ANN_PREDICATE_TPL = "bind_func(\"%1%\", %2%)";
+const char *FUNCTION_ANN_PREDICATE = "bind_func";
+
+const char *TRANSCEND_PASS_SECTION = "% == STATIC ANALYSIS: ANNOTATIONS ==";
+const char *FUNCTION_PREDICATE_TPL = "function(\"%1%\")";
+const char *SITE_SYMBOL_PREDICATE = "s";
+const char *SITE_ANON_PREDICATE = "a";
+const char *DEMAND_FORMAL_PREDICATE = "func_demand";
+const char *DEMAND_ACTUAL_PREDICATE = "func_supply";
+const char *FN_ENTRY_PREDICATE = "entry";
+const char *POLYMORPH_SUPPLY_PREDICATE = "func_supply_guard";
+
+const char *CONTAINERS_ID_IMPL_PREDICATE = "containers_impl";
+const char *CONTAINERS_ID_LINKLIST_PREDICATE = "linkedlist";
+const char *CONTAINERS_IMPL_SOLID_PREDICATE = "solid";
+const char *CONTAINERS_IMPL_ONTHEFLY_PREDICATE = "onthefly";
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/resources.h b/cpp/src/analysis/resources.h
new file mode 100644
index 0000000..6371c0a
--- /dev/null
+++ b/cpp/src/analysis/resources.h
@@ -0,0 +1,37 @@
+//
+// Created by pgess on 15/01/2020.
+//
+#ifndef XREATE_RESOURCES_H
+#define XREATE_RESOURCES_H
+#include "transcendlayer.h"
+#include <tuple>
+#include <string>
+
+namespace xreate{namespace analysis {
+extern const char *FUNCTION_PREDICATE_TPL;
+extern const char *FUNCTION_ANN_PREDICATE_TPL;
+extern const char *FUNCTION_ANN_PREDICATE;
+extern const char *SCOPE_ANN_PREDICATE_TPL;
+extern const char *SCOPE_ANN_PREDICATE;
+extern const char *VAR_ANN_PREDICATE_TPL;
+extern const char *VAR_ANN_PREDICATE;
+extern const char *TRANSCEND_PASS_SECTION;
+extern const char *SITE_SYMBOL_PREDICATE;
+extern const char *SITE_ANON_PREDICATE;
+extern const char *DEMAND_FORMAL_PREDICATE;
+extern const char *DEMAND_ACTUAL_PREDICATE;
+extern const char *POLYMORPH_SUPPLY_PREDICATE;
+extern const char *FN_ENTRY_PREDICATE;
+
+extern const char *CONTAINERS_ID_IMPL_PREDICATE;
+extern const char *CONTAINERS_ID_LINKLIST_PREDICATE;
+extern const char *CONTAINERS_IMPL_SOLID_PREDICATE;
+extern const char *CONTAINERS_IMPL_ONTHEFLY_PREDICATE;
+
+typedef std::tuple<std::string, std::string, std::string> DEMAND_FORMAL_SCHEME; //fn, key, type-alias
+typedef std::tuple<xreate::ASTSitePacked, std::string, Gringo::Symbol> DEMAND_ACTUAL_SCHEME; //fn, key, type-alias
+typedef std::tuple<xreate::ASTSitePacked, Gringo::Symbol, std::string> POLYMORPH_SUPPLY_SCHEME; //site, data, type-variant
+
+}}
+
+#endif //XREATE_RESOURCES_H
diff --git a/cpp/src/analysis/transcendtarget.cpp b/cpp/src/analysis/transcendtarget.cpp
new file mode 100644
index 0000000..7b4015c
--- /dev/null
+++ b/cpp/src/analysis/transcendtarget.cpp
@@ -0,0 +1,187 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on: Jan, 2020
+*/
+
+#include "transcendtarget.h"
+#include "analysis/utils.h"
+#include "analysis/resources.h"
+
+#include <boost/format.hpp>
+#include <boost/algorithm/string/join.hpp>
+using namespace std;
+
+namespace xreate{
+
+void
+TranscendPass::process(ManagedFnPtr function){
+ boost::format formatFn(analysis::FUNCTION_PREDICATE_TPL);
+ boost::format formatFnAnn(analysis::FUNCTION_ANN_PREDICATE_TPL);
+
+ __output << endl << analysis::TRANSCEND_PASS_SECTION << endl;
+ __output << formatFn
+ % (function->getName())
+ << "." << std::endl;
+
+ for(const auto &tagRec: function->getTags()){
+ const Expression &tag = tagRec.second;
+
+ TranscendScope* scopeTr = getRootScope();
+ list<string> definitions;
+ const string& partTagRaw = scopeTr->compile(tag, definitions);
+ TranscendScope::rule(__output,
+ boost::str(formatFnAnn
+ % (function->getName())
+ % (partTagRaw)),
+ definitions);
+
+ __output << endl;
+ }
+
+ return Parent::process(function);
+}
+
+void
+TranscendPass::process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl) {
+ TranscendLayer* transcend = man->transcend;
+ boost::format formatScopeAnn(analysis::SCOPE_ANN_PREDICATE_TPL);
+ ScopePacked scopeId = transcend->pack(scope);
+ TranscendScope* scopeTr = getScope(scope);
+
+ for (const auto& tag : scope->tags){
+ list<string> definitions;
+ const string& partTagRaw = scopeTr->compile(tag, definitions);
+ TranscendScope::rule(__output,
+ boost::str(formatScopeAnn
+ % scopeId
+ % (partTagRaw)),
+ definitions);
+
+ __output << endl;
+ }
+
+ return Parent::process(scope, context, hintBlockDecl);
+}
+
+void
+TranscendPass::process(const Expression &expression, PassContext context, const std::string &varDecl){
+ boost::format formatVarAnn(analysis::VAR_ANN_PREDICATE_TPL);
+ TranscendLayer* transcend = man->transcend;
+ TranscendScope* scopeTr = getScope(context.scope);
+
+ for (const auto& tag: expression.tags){
+ list<string> body;
+ const string& head = scopeTr->compile(tag.second, body);
+
+ TranscendScope::rule(__output,
+ boost::str(formatVarAnn
+ % Parent::man->transcend->pack(ASTSite{expression.id}).str()
+ % head), body);
+ }
+
+ return Parent::process(expression, context, varDecl);
+}
+
+TranscendScope*
+TranscendPass::getScope(const CodeScope * const scope){
+ if(__scopes.count(scope)){
+ return __scopes.at(scope);
+ }
+
+ TranscendScope* unit(new TranscendScope(scope, this));
+ __scopes[scope] = unit;
+ return unit;
+}
+
+void
+TranscendPass::finish(){
+ Parent::man->transcend->addRawScript(__output.str());
+}
+
+std::string
+TranscendScope::compile(const Expression &e, std::list<std::string>& definitions){
+ switch(e.__state){
+ case Expression::COMPOUND: {
+ switch (e.op){
+ case Operator::VARIANT: {
+ const string& predicate = escapePredicate(string(e.getValueString()));
+
+ if(!e.operands.size()){
+ return predicate;
+ }
+
+ list<string> operands;
+ std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
+ [this, &definitions](const Expression &e) {
+ return this->compile(e, definitions);
+ });
+
+ return boost::str(
+ boost::format("%1%(%2%)")
+ % predicate
+ % boost::algorithm::join(operands, ", "));
+ }
+ default: {
+ return analysis::getSite(e, __pass->man->transcend).str();
+ }
+ }
+ }
+
+ case Expression::NUMBER: {
+ return to_string((unsigned int)e.getValueDouble());
+ break;
+ }
+
+ case Expression::STRING: {
+ return boost::str(boost::format("\"%1%\"") % e.getValueString());
+ }
+
+ case Expression::IDENT: {
+ Symbol s = Attachments::get<IdentifierSymbol>(e);
+ const string& identSafe = escapeVar(string(e.getValueString()));
+ const Expression& symbDefinition = CodeScope::getDefinition(s);
+ definitions.push_back(boost::str(boost::format("%1% = %2%")
+ % identSafe
+ % compile(symbDefinition, definitions)
+ ));
+
+ return identSafe;
+ }
+
+ case Expression::INVALID: case Expression::BINDING: assert(false);
+ }
+
+ assert(false);
+ return "";
+}
+
+std::string
+TranscendScope::escapeVar(std::string&& var){
+ assert(var.size());
+
+ var[0] = std::toupper(var[0]);
+ return var;
+}
+
+std::string
+TranscendScope::escapePredicate(std::string&& pred){
+ assert(pred.size());
+
+ pred[0] = std::tolower(pred[0]);
+ return pred;
+}
+
+void
+TranscendScope::rule(std::ostringstream& output, const std::string& head, const std::list<std::string>& body){
+ output << head;
+
+ const string& partBody = boost::join(body, ";");
+ if (!partBody.empty()){
+ output << " :- " << partBody;
+ }
+ output << ".";
+}
+}
\ No newline at end of file
diff --git a/cpp/src/analysis/transcendtarget.h b/cpp/src/analysis/transcendtarget.h
new file mode 100644
index 0000000..9cb4775
--- /dev/null
+++ b/cpp/src/analysis/transcendtarget.h
@@ -0,0 +1,87 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on: Jan, 2020
+*/
+#ifndef XREATE_TRANSCENDTARGET_H
+#define XREATE_TRANSCENDTARGET_H
+
+#include "pass/abstractpass.h"
+#include "transcendlayer.h"
+
+namespace xreate{
+//struct TranscendTag{};
+//class TranscendScope;
+//class TranscendFn;
+//class TranscendTarget;
+//
+//typedef std::list<std::string> TranscendResult;
+//
+//template<>
+//struct compilation::TargetInfo<TranscendTag>{
+//public:
+// typedef TranscendResult Result;
+// typedef TranscendFn Function;
+// typedef TranscendScope Scope;
+//};
+//
+//class TranscendScope: public compilation::Scope<TranscendTag>{
+// typedef compilation::Scope<TranscendTag> Parent;
+//
+//public:
+// TranscendScope(const CodeScope* codeScope, compilation::Function<TranscendTag>* f): Parent(codeScope, f){}
+// TranscendResult processMetaSymbol(const Symbol& s);
+// TranscendResult processMetaExpression(const Expression& expression);
+//
+// virtual TranscendResult process(const Expression& expression) override;
+//};
+//
+//class TranscendFn: public compilation::Function<TranscendTag>{
+// typedef compilation::Function<TranscendTag> Parent;
+//
+//public:
+// TranscendFn(const ManagedFnPtr& fn, compilation::Target<TranscendTag>* target): Parent(fn, target){}
+// virtual TranscendResult process(const std::vector<TranscendResult>& args) override;
+//};
+//
+//class TranscendTarget: public compilation::Target<TranscendTag>{
+//public:
+// virtual void run() override;
+//};
+
+class TranscendPass;
+
+class TranscendScope {
+public:
+ TranscendScope(const CodeScope* scope, const TranscendPass* pass): __pass(pass){}
+ std::string compile(const Expression& e, std::list<std::string>& definitions);
+ static void rule(std::ostringstream& output, const std::string& head, const std::list<std::string>& body);
+
+private:
+ const TranscendPass* __pass;
+ std::string escapeVar(std::string&& var);
+ std::string escapePredicate(std::string&& pred);
+
+};
+
+class TranscendPass: public AbstractPass<void>{
+ typedef AbstractPass<void> Parent;
+
+public:
+ TranscendPass(PassManager* manager): Parent(manager){}
+ void process(ManagedFnPtr function) override;
+ void process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl = "") override;
+ void process(const Expression &expression, PassContext context, const std::string &varDecl = "") override;
+ void finish() override;
+
+private:
+ std::map<const CodeScope*, TranscendScope*> __scopes;
+ std::ostringstream __output;
+
+ TranscendScope* getScope(const CodeScope * const scope);
+ TranscendScope* getRootScope() {return getScope(0); }
+};
+}
+#endif //XREATE_TRANSCENDTARGET_H
diff --git a/cpp/src/analysis/typehints.cpp b/cpp/src/analysis/typehints.cpp
new file mode 100644
index 0000000..a0a6603
--- /dev/null
+++ b/cpp/src/analysis/typehints.cpp
@@ -0,0 +1,52 @@
+//
+// Created by pgess on 24/03/2020.
+//
+
+#include "analysis/typehints.h"
+#include "analysis/predefinedanns.h"
+#include "analysis/utils.h"
+
+namespace xreate{namespace typehints{
+
+namespace impl {
+template<class Hint>
+inline Hint getHint(const Expression& e, const Hint& def, unsigned annId, const ExpandedType& hintT){
+ std::list<Expression> hintsL;
+ auto predefined = analysis::PredefinedAnns::instance();
+ for(const auto& tag: e.tags){hintsL.push_back(tag.second);}
+ const Expression& hintActual = analysis::findAnnById(annId, hintT, hintsL);
+ if (!hintActual.isValid()){
+ return def;
+ }
+
+ return parse<Hint>(hintActual);
+}
+}
+
+template<> IntBits parse(const Expression& e){
+ return {(unsigned) e.operands.at(0).getValueDouble()};
+}
+
+template<> Array parse(const Expression& e){
+ return {(unsigned) e.operands.at(0).getValueDouble()};
+}
+
+template<>
+IntBits getHint(const Expression& e, const IntBits& def){
+ auto predefined = analysis::PredefinedAnns::instance();
+ return impl::getHint<IntBits>(e, def,
+ (unsigned) analysis::PredefinedAnns::IntHints::SIZE,
+ ExpandedType(predefined.hintsIntT)
+ );
+}
+
+template<>
+Array getHint(const Expression& e, const Array& def){
+ auto predefined = analysis::PredefinedAnns::instance();
+ return impl::getHint<Array>(e, def,
+ (unsigned) analysis::PredefinedAnns::ContHints::ARRAY,
+ ExpandedType(predefined.hintsContT)
+ );
+}
+
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/typehints.h b/cpp/src/analysis/typehints.h
new file mode 100644
index 0000000..67028cc
--- /dev/null
+++ b/cpp/src/analysis/typehints.h
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * typehints.h
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ */
+
+/**
+ * \file typehints.h
+ * \brief Type inference hints
+ */
+#ifndef XREATE_TYPEHINTS_H
+#define XREATE_TYPEHINTS_H
+
+#include "ast.h"
+
+namespace xreate{namespace typehints{
+
+struct IntBits{
+ unsigned int size;
+};
+
+struct Array{
+ size_t size;
+};
+
+template<class Typ>
+Typ getHint(const Expression& e, const Typ& def);
+
+template<>
+IntBits getHint(const Expression& e, const IntBits& def);
+
+template<>
+Array getHint(const Expression& e, const Array& def);
+
+template<class Typ>
+Typ parse(const Expression& e);
+
+template<> IntBits parse(const Expression& e);
+template<> Array parse(const Expression& e);
+
+}}
+
+#endif //XREATE_TYPEHINTS_H
diff --git a/cpp/src/analysis/typeinference.cpp b/cpp/src/analysis/typeinference.cpp
index c6d2b5a..fce6d88 100644
--- a/cpp/src/analysis/typeinference.cpp
+++ b/cpp/src/analysis/typeinference.cpp
@@ -1,98 +1,114 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* typeinference.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 16, 2017, 10:13 AM
*/
/**
* \file typeinference.h
* \brief Type inference analysis
*/
#include "typeinference.h"
#include "llvmlayer.h"
#include "transcendlayer.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DerivedTypes.h"
using namespace std;
namespace xreate{
namespace typeinference{
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissallow based on annotations)
llvm::Value*
doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder) {
- if(tyTarget->isIntegerTy() && source->getType()->isIntegerTy()) {
- llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
- llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
-
- if(tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()) {
- return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
- }
-
- if(tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()) {
- return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
- }
- }
-
- if(source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()) {
- return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
- }
-
- if (source->getType()->isStructTy() && tyTarget->isIntegerTy()){
- llvm::StructType* sourceST = llvm::cast<llvm::StructType>(source->getType());
- if(sourceST->getNumElements() == 1) {
- llvm::Value* sourceElRaw = builder.CreateExtractValue(source, llvm::ArrayRef<unsigned>({0}));
- return doAutomaticTypeConversion(sourceElRaw, tyTarget, builder);
- }
- }
-
- return source;
+ if (!tyTarget) return source;
+ if(tyTarget->isIntegerTy() && source->getType()->isIntegerTy()) {
+ llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
+ llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
+
+ if(tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()) {
+ return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
+ }
+
+ if(tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()) {
+ return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
+ }
+ }
+
+ if(source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()) {
+ return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
+ }
+
+ if (source->getType()->isStructTy() && tyTarget->isIntegerTy()){
+ llvm::StructType* sourceST = llvm::cast<llvm::StructType>(source->getType());
+ if(sourceST->getNumElements() == 1) {
+ llvm::Value* sourceElRaw = builder.CreateExtractValue(source, llvm::ArrayRef<unsigned>({0}));
+ return doAutomaticTypeConversion(sourceElRaw, tyTarget, builder);
+ }
+ }
+
+ return source;
}
/**
* \brief Performs basic type inference to deduce the type of the given expression
*
* Tries several strategies in the following order:
* - Looks at expression's type if it has one.
* - Looks at Attachment<TypeInferred> if it has one. This allows assign expression's type by analyses done elsewhere.
* - For a number literal assumes i32.
*
* \param expression Infers the given expression's type.
* \param ast AST instance.
*/
ExpandedType
-getType(const Expression& expression, const AST& ast) {
- if(expression.type.isValid()) {
- return ast.expandType(expression.type);
- }
+getType(const Expression& expression, const TypeAnnotation& expectedT, const AST& ast) {
+ if(expression.type.isValid()) {
+ return ast.expandType(expression.type);
+ }
- if(expression.__state == Expression::IDENT) {
- Symbol s = Attachments::get<IdentifierSymbol>(expression);
- return getType(CodeScope::getDefinition(s), ast);
- }
+ if(expectedT.isValid()){
+ return ast.expandType(expectedT);
+ }
- if(Attachments::exists<TypeInferred>(expression)) {
- return Attachments::get<TypeInferred>(expression);
- }
+ if(Attachments::exists<TypeInferred>(expression)) {
+ return Attachments::get<TypeInferred>(expression);
+ }
- if(expression.__state == Expression::NUMBER) {
- return ExpandedType(TypeAnnotation(TypePrimitive::I32));
- }
+ if(expression.__state == Expression::IDENT) {
+ Symbol s = Attachments::get<IdentifierSymbol>(expression);
+ return getType(CodeScope::getDefinition(s), TypeAnnotation(), ast);
+ }
+
+ if(expression.__state == Expression::NUMBER) {
+ return ExpandedType(TypeAnnotation(TypePrimitive::Int));
+ }
+ assert(false && "Type can't be determined for an expression");
+}
+
+ExpandedType
+getSubtype(const ExpandedType& type, const std::string& index){
+ for(size_t idx = 0; idx < type->fields.size(); ++idx){
+ if (index == type->fields.at(idx)){
+ return ExpandedType(type->__operands.at(idx));
+ }
+ }
- assert(false && "Type can't be determined for an expression");
+ assert(false);
+ return ExpandedType(TypeAnnotation());
}
}
} //end of namespace xreate::typeinference
diff --git a/cpp/src/analysis/typeinference.h b/cpp/src/analysis/typeinference.h
index 1990995..f7207e9 100644
--- a/cpp/src/analysis/typeinference.h
+++ b/cpp/src/analysis/typeinference.h
@@ -1,36 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: typeinference.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on April 16, 2017, 10:17 AM
*/
#ifndef TYPEINFERENCE_H
#define TYPEINFERENCE_H
#include "ast.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm{
class Value;
class Type;
};
namespace xreate{ namespace typeinference{
/**
* \brief Casts the given variable to the given type
* \param source The variable that needs casting
* \param tyTarget The type to cast to
* \param builder Instance of llvm's IRBuilder
*/
llvm::Value* doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder);
-ExpandedType getType(const Expression& expression, const AST& ast);
+ExpandedType getType(const Expression& expression, const TypeAnnotation& expectedT, const AST& ast);
+ExpandedType getSubtype(const ExpandedType& type, const std::string& index);
}
}//namespace xreate::typeinference
#endif /* TYPEINFERENCE_H */
diff --git a/cpp/src/analysis/utils.cpp b/cpp/src/analysis/utils.cpp
index 1d8df75..a7e13bd 100644
--- a/cpp/src/analysis/utils.cpp
+++ b/cpp/src/analysis/utils.cpp
@@ -1,159 +1,425 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* aux.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file src/analysis/utils.h
* \brief Various reasoning related utilities
*/
#include "utils.h"
+#include "resources.h"
#include <boost/format.hpp>
using namespace std;
namespace xreate { namespace analysis {
-std::list<std::string>
-compile(const Expression &e){
- list<string> result;
-
- switch (e.op) {
- case Operator::CALL: {
- if(!e.operands.size()){
- result.push_back(e.getValueString());
- break;
- }
-
- std::list<list<string>> operands;
- std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
- [](const Expression &e) {
- return compile(e);
- });
-
- list<string> &&operands_ = multiplyLists(std::move(operands));
- result.push_back(boost::str(boost::format("%1%(%2%)") % (e.getValueString()) % (boost::algorithm::join(operands_, ", "))));
- break;
- }
+//std::list<std::string> multiplyLists(std::list<std::list<std::string>> &&lists){
+// assert(false);
+//}
+//
+//std::list<std::string>
+//compile(const Expression &e){
+// list<string> result;
+//
+// switch (e.op) {
+// case Operator::CALL: {
+//
+// }
+//
+// case Operator::NEG: {
+// assert(e.operands.size() == 1);
+//
+// const Expression &op = e.operands.at(0);
+// list<string> &&rawOp = compile(op);
+//
+// assert(rawOp.size() == 1);
+// result.push_back((boost::format("not %1%")%(rawOp.front())).str());
+// break;
+// };
+//
+// case Operator::INVALID: {
+// switch (e.__state) {
+// case Expression::IDENT:
+// result.push_back(e.getValueString());
+// break;
+//
+// case Expression::NUMBER:
+// result.push_back(to_string(e.getValueDouble()));
+// break;
+//
+// default:
+// assert(true);
+// }
+// break;
+// }
+//
+// default: break;
+// }
+//
+// assert(result.size());
+// return result;
+//}
+//
+//std::list<std::string>
+//compileNeg(const Expression &e){
+// list<string> result;
+// switch (e.op) {
+// case Operator::IMPL: {
+// assert(e.__state == Expression::COMPOUND);
+// assert(e.operands.size() == 2);
+// list<string> operands1 = compile(e.operands.at(0));
+// list<string> operands2 = compile(e.operands.at(1));
+//
+// boost::format formatNeg("%1%, not %2%");
+// for (const auto &op1: operands1)
+// for (const auto &op2: operands2) {
+// result.push_back(boost::str(formatNeg %(op1) % (op2)));
+// }
+// break;
+// }
+// case Operator::NEG: {
+// assert(e.operands.size() == 1);
+//
+// const Expression &op = e.operands.at(0);
+// list<string> &&rawOp = compile(op);
+//
+// assert(rawOp.size() == 1);
+// result.push_back(rawOp.front());
+// break;
+// };
+//
+// default:
+// assert(true);
+// }
+//
+// return result;
+//}
+//
+////NOTE: Any changes should be reflected in ParseImplAtom<SymbolPacked>,
+//// ParseImplAtom<SymbolNode>
+//class VisitorFormatSymbol: public boost::static_visitor<boost::format> {
+//public:
+//
+// boost::format operator()(const SymbolPacked& node) const {
+// boost::format formatSymbNamed("s(%1%,%2%,%3%)");
+// return formatSymbNamed % node.identifier % node.version % node.scope ;
+// }
+//
+// boost::format operator()(const SymbolAnonymous& node) const {
+// boost::format formatSymbAnonymous("a(%1%)");
+// return formatSymbAnonymous % node.id;
+// }
+//};
+//
+//boost::format writeSymbolNode(const SymbolNode& symbol){
+// return boost::apply_visitor(VisitorFormatSymbol(), symbol);
+//}
+
+typedef vector<int> InstancePacked;
+
+std::list<Expression>
+generateAllInstancesInDomain2(const ExpandedType& domainT) {
+ if(!domainT->isValid()) {
+ return {Expression()};
+ }
+ assert(domainT->__operator == TypeOperator::VARIANT);
+ std::list<Expression> results;
+ int variantId = -1;
+
+ bool flagDomainStateless = std::all_of(domainT->__operands.begin(), domainT->__operands.end(),
+ [](const TypeAnnotation & subdomainT) {
+ return !subdomainT.isValid();
+ });
+
+ for(const TypeAnnotation& subdomainT : domainT->__operands) {
+ ++variantId;
+
+ if(flagDomainStateless) {
+ Expression result(Operator::VARIANT,{});
+ result.setValueDouble(variantId);
+ results.push_back(result);
+ continue;
+ }
- case Operator::NEG: {
- assert(e.operands.size() == 1);
+ std::list<Expression> subresults = generateAllInstancesInDomain2(ExpandedType(subdomainT));
+ for (const Expression& subresult : subresults) {
+ Expression result(Operator::VARIANT,{});
+ result.setValueDouble(variantId);
+ result.operands.push_back(subresult);
- const Expression &op = e.operands.at(0);
- list<string> &&rawOp = compile(op);
+ results.push_back(result);
+ }
+ }
- assert(rawOp.size() == 1);
- result.push_back((boost::format("not %1%")%(rawOp.front())).str());
- break;
- };
+ return results;
+}
- case Operator::INVALID: {
- switch (e.__state) {
- case Expression::IDENT:
- result.push_back(e.getValueString());
- break;
+TypeAnnotation
+collapseFnGroup(const std::list<Gringo::Symbol>& symbols) {
+ Gringo::Symbol symbolAny = symbols.front();
+ size_t operandsCount = symbolAny.args().size;
- case Expression::NUMBER:
- result.push_back(to_string(e.getValueDouble()));
- break;
+ TypeAnnotation resultT;
+ resultT.__operands.reserve(operandsCount);
- default:
- assert(true);
- }
- break;
- }
+ for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
+ std::list<Gringo::Symbol> column;
- default: break;
+ for(const Gringo::Symbol& row : symbols) {
+ column.push_back(row.args()[operandId]);
}
- assert(result.size());
- return result;
+ TypeAnnotation operandT = collapseColumn(column);
+ resultT.__operands.push_back(operandT);
+ }
+
+ if(resultT.__operands.size() == 1) {
+ return resultT.__operands.front();
+ }
+
+ if(resultT.__operands.size() > 1) {
+ resultT.__operator = TypeOperator::RECORD;
+ return resultT;
+ }
+
+ return resultT;
}
-list<string>
-multiplyLists(list<list<string>> &&lists) {
- typedef list<string> StringList;
- assert(lists.size());
- StringList result(*lists.begin());
- lists.pop_front();
+TypeAnnotation
+collapseColumn(const std::list<Gringo::Symbol>& symbols) {
+ TypeAnnotation resultT;
+ if(!symbols.size()) return resultT;
- 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;
+ Gringo::Symbol symbolAny = symbols.front();
- 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)));
+ switch(symbolAny.type()) {
+ case Gringo::SymbolType::Num:
+ {
+ return TypeAnnotation(TypePrimitive::Int);
+ }
- *expr1I = str(concat %(*expr1I) %(*expr2I));
- }
+ case Gringo::SymbolType::Str:
+ {
+ return TypeAnnotation(TypePrimitive::String);
}
- return result;
+ case Gringo::SymbolType::Fun:
+ {
+ map<string, list < Gringo::Symbol>> fnGroups;
+
+ for(const Gringo::Symbol& row : symbols) {
+ fnGroups[row.name().c_str()].push_back(row);
+ }
+
+ TypeAnnotation resultT;
+ resultT.__operands.reserve(fnGroups.size());
+ resultT.bindings.reserve(fnGroups.size());
+
+ for(const auto& group : fnGroups) {
+ if(!group.second.size()) continue;
+
+ TypeAnnotation variantT = collapseFnGroup(group.second);
+ Gringo::Symbol symbolAny = group.second.front();
+ string variantName = symbolAny.name().c_str();
+ resultT.fields.push_back(variantName);
+ resultT.__operands.push_back(variantT);
+ }
+
+ resultT.__operator = TypeOperator::VARIANT;
+ // if(resultT.__operands.size() == 1) {
+ // return resultT.__operands.front();
+ // }
+ return resultT;
+ }
+
+ case Gringo::SymbolType::Inf:
+ case Gringo::SymbolType::Special:
+ case Gringo::SymbolType::Sup:
+ {
+ break;
+ }
+ }
+
+ assert(false);
+ return TypeAnnotation();
+}
+
+ExpandedType
+dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend) {
+ assert(t->__operator == TypeOperator::SLAVE);
+ const string& domain = t->__valueCustom;
+ StaticModel model = transcend->query(domain);
+ if(!model.size()) return ExpandedType(TypeAnnotation());
+
+ std::list<Gringo::Symbol> symbols;
+ for(auto row : model) {
+ symbols.push_back(row.second);
+ }
+ return ExpandedType(collapseFnGroup(symbols));
+}
+
+ASTSitePacked
+getSite(const Expression& e, TranscendLayer* transcend){
+ Attachments::put<ExprId_A>(e, e);
+ return transcend->pack(ASTSite{e.id});
+}
+
+Expression
+recognizeSite(const Gringo::Symbol& atom, const ExpandedType& schemaT, TranscendLayer* transcend)
+{
+ if(atom.type()!=Gringo::SymbolType::Fun) return Expression();
+ string predicateName = atom.name().c_str();
+ if (predicateName != SITE_SYMBOL_PREDICATE && predicateName != SITE_ANON_PREDICATE)
+ return Expression();
+
+ const ASTSitePacked& siteP = TranscendLayer::parseAtom<ASTSitePacked>(atom);
+ const ASTSite& site = transcend->unpack(siteP);
+ return site.getDefinition();
}
-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;
+Expression
+representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend) {
+ const Expression siteExpr = recognizeSite(atom, schemaT, transcend);
+ if (siteExpr.isValid()) return siteExpr;
+
+ switch(schemaT->__operator) {
+ case TypeOperator::NONE:
+ {
+ switch(schemaT->__value) {
+ case TypePrimitive::I8:
+ case TypePrimitive::I32:
+ case TypePrimitive::I64:
+ case TypePrimitive::Int:
+ {
+ return Expression(Atom<Number_t>(atom.num()));
}
- case Operator::NEG: {
- assert(e.operands.size() == 1);
- const Expression &op = e.operands.at(0);
- list<string> &&rawOp = compile(op);
+ case TypePrimitive::String:
+ {
+ return Expression(Atom<String_t>(atom.string().c_str()));
+ }
- assert(rawOp.size() == 1);
- result.push_back(rawOp.front());
- break;
- };
+ case TypePrimitive::Invalid:
+ case TypePrimitive::Bool:
+ case TypePrimitive::Float:
+ {
+ assert(false);
+ return Expression();
+ }
+ }
+ break;
+ }
- default:
- assert(true);
+ case TypeOperator::SLAVE:
+ {
+ ExpandedType contentT = dereferenceSlaveType(schemaT, transcend);
+ return representTransExpression(atom, contentT, transcend);
}
- return result;
-}
+ case TypeOperator::VARIANT:
+ {
+ map<string, int> dictVariants;
+ for(size_t variantId = 0; variantId < schemaT->fields.size(); ++variantId) {
+ dictVariants.emplace(schemaT->fields.at(variantId), variantId);
+ }
+
+ string predicateName = atom.name().c_str();
+ assert(dictVariants.count(predicateName));
+
+ size_t predicateId = dictVariants.at(predicateName);
+ Expression result(Operator::VARIANT,{});
+ result.op = Operator::VARIANT;
+ result.setValueDouble(predicateId);
+
+ if(!schemaT->__operands.size()) return result;
+ ExpandedType schemeOperands = schemaT->__operands.at(predicateId).__operator == TypeOperator::SLAVE
+ ? dereferenceSlaveType(ExpandedType(schemaT->__operands.at(predicateId)), transcend)
+ : ExpandedType(schemaT->__operands.at(predicateId));
+
+ if (schemeOperands->__operator == TypeOperator::RECORD){
+ Expression operandsList = representTransExpression(atom, schemeOperands, transcend);
+ result.operands = move(operandsList.operands);
+
+ } else if(!schemeOperands->isValid()) {
+ assert(atom.args().size == 0);
+ return result;
+
+ } else {
+ assert(false);
+ }
-//NOTE: Any changes should be reflected in ParseImplAtom<SymbolPacked>,
-// ParseImplAtom<SymbolNode>
-class VisitorFormatSymbol: public boost::static_visitor<boost::format> {
-public:
+ return result;
+ }
- boost::format operator()(const SymbolPacked& node) const {
- boost::format formatSymbNamed("s(%1%,%2%,%3%)");
- return formatSymbNamed % node.identifier % node.version % node.scope ;
+ case TypeOperator::RECORD:
+ {
+ const Gringo::SymSpan& operandsRaw = atom.args();
+ size_t opCount = operandsRaw.size;
+ assert(opCount == schemaT->__operands.size());
+
+ size_t operandId = 0;
+ std::vector<Expression> operands;
+ operands.reserve(opCount);
+ for(const TypeAnnotation operandT : schemaT->__operands) {
+ operands.push_back(representTransExpression(operandsRaw[operandId], ExpandedType(operandT), transcend));
+ ++operandId;
+ }
+
+ Expression result(Operator::LIST,{});
+ result.operands = operands;
+ result.type = schemaT;
+ return result;
}
- boost::format operator()(const SymbolAnonymous& node) const {
- boost::format formatSymbAnonymous("a(%1%)");
- return formatSymbAnonymous % node.id;
+ case TypeOperator::ARRAY:
+ case TypeOperator::ALIAS:
+ case TypeOperator::ACCESS:
+ case TypeOperator::REF:
+ case TypeOperator::VOID:
+ case TypeOperator::GUARD:
+ {
+ assert(false);
+ return Expression();
}
-};
+ }
+
+ assert(false);
+ return Expression();
+}
+
+Expression
+representVecStr(const std::vector<std::string>& srcList){
+ Expression dstE(Operator::LIST, {});
+
+ for(const string op: srcList){
+ dstE.operands.push_back(Atom<String_t>(string(op)));
+ }
+
+ return dstE;
+}
+
+Expression
+findAnnById(unsigned annId, const ExpandedType& annT, const std::list<Expression>& annotations){
+ assert(annT->fields.size() > annId);
+ const string& annExpectedS = annT->fields.at(annId);
+
+ for(const Expression& e: annotations){
+ if (e.type.fields.size() <= annId) continue;
+ const string& annTestS = e.type.fields.at(annId);
+
+ if (annTestS == annExpectedS) return e;
+ }
-boost::format writeSymbolNode(const SymbolNode& symbol){
- return boost::apply_visitor(VisitorFormatSymbol(), symbol);
+ return Expression();
}
}} //end of xreate::analysis
diff --git a/cpp/src/analysis/utils.h b/cpp/src/analysis/utils.h
index 82c325b..c47a0ee 100644
--- a/cpp/src/analysis/utils.h
+++ b/cpp/src/analysis/utils.h
@@ -1,36 +1,59 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: aux.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:49 PM
*/
#ifndef AUX_H
#define AUX_H
#include "ast.h"
#include "transcendlayer.h"
#include <list>
#include <boost/format.hpp>
namespace xreate { namespace analysis {
/**
* \brief Compiles Xreate expression into ASP format recognizable by an external ASP solver.
* @param e expression
* @return textual expression's representation in an ASP format.
*/
std::list<std::string> compile(const Expression &e);
std::list<std::string> compileNeg(const Expression &e);
std::list<std::string> multiplyLists(std::list<std::list<std::string>> &&lists);
-boost::format writeSymbolNode(const SymbolNode& symbol);
+ASTSitePacked getSite(const Expression& e, TranscendLayer* transcend);
+
+/**
+ * \brief Converts a Transcend's fact to a Xreate's expression that can be interpreted further. Supports `query` keyword.
+ * @param atom Transcend's fact
+ * @param schemaT Type of the resulting expression
+ * @param transcend Transcend's instance
+ * @return converted Transcend' fact in form of Xreate's expression
+ */
+Expression representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend);
+
+/**
+ * \brief Expands slave type.
+ * @param t Slave type
+ * @param transcend Instance of Transcend
+ * @return The expanded slave type
+ */
+ExpandedType dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend);
+
+TypeAnnotation collapseColumn(const std::list<Gringo::Symbol>& symbols);
+std::list<Expression> generateAllInstancesInDomain2(const ExpandedType& domainT);
+
+Expression representVecStr(const std::vector<std::string>& srcList);
+Expression findAnnById(unsigned annId, const ExpandedType& annT, const std::list<Expression>& annotations);
}} //end of xreate::analysis
#endif /* AUX_H */
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 2c24707..fd5eaec 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,971 +1,961 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: ast.cpp
*/
#include "ast.h"
-#include "ExternLayer.h"
#include "analysis/typeinference.h"
+#include "analysis/predefinedanns.h"
+
+#ifdef XREATE_ENABLE_EXTERN
+ #include "ExternLayer.h"
+#endif
#include <stdexcept>
#include <iostream>
//TODO BDecl. forbid multiple body declaration (ExprTyped)
namespace std {
std::size_t
hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const {
return s.id ^ (s.version << 2);
}
bool
equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const {
return __x.id == __y.id && __x.version == __y.version;
}
size_t
hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const {
return hash<xreate::ScopedSymbol>()(s.identifier) ^ ((long int) s.scope << 1);
}
bool
equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const {
return __x == __y;
};
}
using namespace std;
namespace xreate {
Atom<Identifier_t>::Atom(const std::wstring& value) {
__value = wstring_to_utf8(value);
}
Atom<Identifier_t>::Atom(std::string && name) : __value(name) {
}
const std::string&
Atom<Identifier_t>::get() const {
return __value;
}
Atom<Number_t>::Atom(wchar_t* value) {
//DEBT reconsider number literal recognition
__value = wcstol(value, 0, 10);
}
Atom<Number_t>::Atom(int value)
: __value(value) {
}
double
Atom<Number_t>::get()const {
return __value;
}
Atom<String_t>::Atom(const std::wstring& value) {
assert(value.size() >= 2);
__value = wstring_to_utf8(value.substr(1, value.size() - 2));
}
Atom<String_t>::Atom(std::string && name) : __value(name) {}
const std::string&
Atom<String_t>::get() const {
return __value;
}
/** \brief xreate::Expression static information*/
class ExpressionHints {
public:
static bool
isStringValueValid(const Expression& e) {
switch (e.__state) {
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
return true;
case Expression::NUMBER:
case Expression::BINDING:
return false;
case Expression::COMPOUND:
{
switch (e.op) {
case Operator::CALL:
return true;
default: return false;
}
}
}
return false;
}
static bool
isDoubleValueValid(const Expression& e) {
switch (e.__state) {
case Expression::NUMBER:
return true;
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
case Expression::BINDING:
return false;
case Expression::COMPOUND: {
switch (e.op) {
case Operator::VARIANT:
return true;
default: return false;
}
}
}
return false;
}
};
-class TypesResolver {
-private:
- const AST* ast;
- std::map<std::string, TypeAnnotation> scope;
- std::map<TypeAnnotation, int> signatures;
-
- ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
- return TypesResolver(ast, scope, signatures)(t, args);
- }
-
- std::vector<TypeAnnotation>
- expandOperands(const std::vector<TypeAnnotation>& operands) {
- std::vector<TypeAnnotation> pack;
-
- pack.reserve(operands.size());
- std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
- [this](const TypeAnnotation & t) {
- return expandType(t);
- });
-
- return pack;
- }
-
+class TypeResolver {
public:
+TypeResolver(const AST* ast,
+ TypeResolver * parent,
+ std::set<std::string> trace,
+ const std::map<std::string, TypeAnnotation>& scope = std::map<std::string, TypeAnnotation>())
+ : __ast(ast), __scope(scope), __trace(trace), __parent(parent) {}
- 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 = this->operator()(t.__operands.at(0));
+ return ExpandedType(TypeAnnotation(TypeOperator::ARRAY, {elTy}));
}
- ExpandedType
- operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
- //assert(args.size() == t.bindings.size()); // invalid number of arguments
- for (size_t i = 0; i < args.size(); ++i) {
- scope[t.bindings.at(i)] = args.at(i);
- }
-
- switch (t.__operator) {
- case TypeOperator::LIST_ARRAY:
- {
- assert(t.__operands.size() == 1);
-
- Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
- return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
- }
-
- case TypeOperator::LIST_RECORD:
- {
- std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
- auto typNew = TypeAnnotation(TypeOperator::LIST_RECORD, move(packOperands));
- typNew.fields = t.fields;
-
- return ExpandedType(move(typNew));
- };
-
- case TypeOperator::VARIANT:
- {
- std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
- auto typNew = TypeAnnotation(TypeOperator::VARIANT, move(packOperands));
- typNew.fields = t.fields;
-
- return ExpandedType(move(typNew));
- };
-
- case TypeOperator::CALL:
- {
- std::string alias = t.__valueCustom;
-
- //find in local scope:
- TypeAnnotation ty;
- if (scope.count(alias)) {
- ty = scope.at(alias);
-
- } else if (ast->__indexTypeAliases.count(alias)) {
- ty = ast->__indexTypeAliases.at(alias);
-
- } else {
- assert(false && "Undefined or external type");
- }
-
- std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
- TypeAnnotation signature(TypeOperator::CALL, move(operands));
- signature.__valueCustom = alias;
-
- if (signatures.count(signature)) {
- auto link = TypeAnnotation(TypeOperator::LINK,{});
- link.conjuctionId = signatures.at(signature);
-
- return ExpandedType(move(link));
- }
-
- int cid = signatures.size();
- signatures[signature] = cid;
- TypeAnnotation tyResult = expandType(ty, operands);
- tyResult.conjuctionId = cid;
-
- return ExpandedType(move(tyResult));
- };
-
- case TypeOperator::CUSTOM:
- {
- if (signatures.count(t)) {
- return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
- }
- signatures.emplace(t, signatures.size());
-
- std::string alias = t.__valueCustom;
-
- //find in local scope:
- if (scope.count(alias)) {
- return expandType(scope.at(alias));
- }
-
- //find in general scope:
- if (ast->__indexTypeAliases.count(alias)) {
- return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
- }
+ case TypeOperator::RECORD:
+ {
+ std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
+ auto typNew = TypeAnnotation(TypeOperator::RECORD, move(packOperands));
+ typNew.fields = t.fields;
- //if type is unknown keep it as is.
- return ExpandedType(TypeAnnotation(t));
- };
+ return ExpandedType(move(typNew));
+ };
- case TypeOperator::ACCESS:
- {
- std::string alias = t.__valueCustom;
- ExpandedType tyAlias = ExpandedType(TypeAnnotation());
+ case TypeOperator::VARIANT:
+ {
+ std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
+ auto typNew = TypeAnnotation(TypeOperator::VARIANT, move(packOperands));
+ typNew.fields = t.fields;
- //Find in local scope:
- if (scope.count(alias)) {
- tyAlias = expandType(scope.at(alias));
+ return ExpandedType(move(typNew));
+ };
- //Find in global scope:
- } else if ((ast->__indexTypeAliases.count(alias))) {
- tyAlias = expandType(ast->__indexTypeAliases.at(alias));
+ case TypeOperator::ALIAS: {
+ std::string alias = t.__valueCustom;
+ if (__trace.count(alias)){
+ assert(false && "Recursive Type");
+ return ExpandedType(TypeAnnotation());
+ }
- } else {
- assert(false && "Undefined or external type");
- }
+ const TypeAnnotation& tyAlias = findType(alias);
+ std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
+ auto traceNew =__trace;
+ traceNew.insert(alias);
+ return TypeResolver(__ast, this, traceNew, __scope)(tyAlias, operands);
+ };
- assert(tyAlias->__operator == TypeOperator::LIST_RECORD);
+ case TypeOperator::ACCESS:
+ {
+ std::string alias = t.__valueCustom;
+ const TypeAnnotation& ty = findType(alias);
+ TypeAnnotation tyAggr = this->operator()(ty);
- for (const string& field : t.fields) {
- auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
- assert(fieldIt != tyAlias->fields.end() && "unknown field");
+ for (const string& field : t.fields) {
+ auto fieldIt = std::find(tyAggr.fields.begin(), tyAggr.fields.end(), field);
+ assert(fieldIt != tyAggr.fields.end() && "unknown field");
- int fieldId = fieldIt - tyAlias->fields.begin();
- tyAlias = expandType(tyAlias->__operands.at(fieldId));
- }
+ int fieldId = fieldIt - tyAggr.fields.begin();
+ tyAggr = tyAggr.__operands.at(fieldId);
+ }
- return tyAlias;
- }
+ return ExpandedType(tyAggr);
+ }
- case TypeOperator::NONE:
- {
- return ExpandedType(TypeAnnotation(t));
- }
+ case TypeOperator::NONE:
+ case TypeOperator::VOID:
+ case TypeOperator::SLAVE:
+ case TypeOperator::REF: {
+ return ExpandedType(t);
+ }
- case TypeOperator::SLAVE:
- {
- return ExpandedType(t);
- }
+ default:
+ assert(false);
+ }
- default:
- assert(false);
- }
+ assert(false);
+ return ExpandedType(TypeAnnotation());
+}
- assert(false);
- return ExpandedType(TypeAnnotation());
+private:
+ const AST* __ast;
+ std::map<std::string, TypeAnnotation> __scope;
+ std::set<std::string> __trace;
+ TypeResolver* __parent;
+
+ 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 this->operator()(t);
+ });
+ return pack;
+ }
+
+ TypeAnnotation findType(const std::string& alias){
+ if (__scope.count(alias)) {
+ return __scope.at(alias);
+
+ } else if (__parent){
+ return __parent->findType(alias);
+
+ } else if (__ast->__registryTypes.count(alias)){
+ return __ast->__registryTypes.at(alias);
}
+
+ assert(false && "Undefined or external type");
+ return TypeAnnotation();
+ }
};
TypeAnnotation::TypeAnnotation()
: __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid) {
}
TypeAnnotation::TypeAnnotation(TypePrimitive typ)
-: __value(typ) {
-}
+: __value(typ)
+{}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
: __operator(op), __operands(operands) {
}
-TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
-: TypeAnnotation(TypeOperator::LIST_ARRAY,{typ}) {
- __size = size;
-}
-
bool
TypeAnnotation::isValid() const {
return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
}
bool
TypeAnnotation::operator<(const TypeAnnotation& t) const {
if (__operator != t.__operator) return __operator < t.__operator;
if (__operator == TypeOperator::NONE)
return __value < t.__value;
- if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
+ if (__operator == TypeOperator::ALIAS || __operator == TypeOperator::ACCESS) {
if (__valueCustom != t.__valueCustom)
return __valueCustom < t.__valueCustom;
}
return __operands < t.__operands;
}
/*
TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
{}
*/
void
TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
bindings.reserve(bindings.size() + params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
void
TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
fields.reserve(fields.size() + listFields.size());
std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
unsigned int Expression::nextVacantId = 0;
Expression::Expression(const Atom<Number_t>& number)
: Expression() {
__state = NUMBER;
op = Operator::INVALID;
__valueD = number.get();
}
Expression::Expression(const Atom<String_t>& a)
: Expression() {
__state = STRING;
op = Operator::INVALID;
__valueS = a.get();
}
Expression::Expression(const Atom<Identifier_t> &ident)
: Expression() {
__state = IDENT;
op = Operator::INVALID;
__valueS = ident.get();
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: Expression() {
__state = COMPOUND;
op = oprt;
if (op == Operator::CALL) {
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
operands.insert(operands.end(), params.begin() + 1, params.end());
return;
}
operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt) {
op = oprt;
switch (op) {
case Operator::INVALID:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg) {
operands.push_back(arg);
}
void
Expression::addTags(const std::list<Expression> tags) const {
std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
[](const Expression & tag) {
return make_pair(tag.getValueString(), tag);
});
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
addBindings(params.begin(), params.end());
}
void
Expression::bindType(TypeAnnotation t) {
type = move(t);
}
void
Expression::addBlock(ManagedScpPtr scope) {
blocks.push_back(scope.operator->());
}
const std::vector<Expression>&
Expression::getOperands() const {
return operands;
}
double
Expression::getValueDouble() const {
return __valueD;
}
const std::string&
Expression::getValueString() const {
return __valueS;
}
void
Expression::setValue(const Atom<Identifier_t>&& v) {
__valueS = v.get();
}
void Expression::setValueDouble(double value) {
__valueD = value;
}
bool
Expression::isValid() const {
return (__state != INVALID);
}
bool
Expression::isDefined() const {
return (__state != BINDING && __state != INVALID);
}
Expression::Expression()
: __state(INVALID), op(Operator::INVALID), id(nextVacantId++) {
}
namespace details { namespace inconsistent {
+std::map<std::string, IntrinsicFn>
+AST::__registryIntrinsics = {};
+
AST::AST() {
- Attachments::init<versions::VariableVersion>();
- Attachments::init<IdentifierSymbol>();
- Attachments::init<SymbolAlias>();
- Attachments::init<TypeInferred>();
+ Attachments::init<versions::VariableVersion>();
+ Attachments::init<IdentifierSymbol>();
+ Attachments::init<ExprAlias_A>();
+ Attachments::init<TypeInferred>();
+ Attachments::init<ExprId_A>();
+
+ initIntrinsics();
+ analysis::PredefinedAnns::instance().fillRegistry(__registryVariants);
}
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());
+AST::addExternData(ExternData &&entry) {
+ //__externdata.push_back(entry);
}
void
AST::add(Function* f) {
__functions.push_back(f);
- __indexFunctions.emplace(f->getName(), __functions.size() - 1);
+ __dictFunctions.emplace(f->getName(), __functions.size() - 1);
}
void
AST::add(MetaRuleAbstract *r) {
__rules.push_back(r);
}
void
AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
if (t.__operator == TypeOperator::VARIANT) {
for (int i = 0, size = t.fields.size(); i < size; ++i) {
- __dictVariants.emplace(t.fields[i], make_pair(t, i));
+ __registryVariants.emplace(t.fields[i], make_pair(t, i));
}
}
- __indexTypeAliases.emplace(alias.get(), move(t));
+ __registryTypes.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 = __dictFunctions.count(name);
if (!count) {
return ManagedFnPtr::Invalid();
}
assert(count == 1);
- auto range = __indexFunctions.equal_range(name);
+ auto range = __dictFunctions.equal_range(name);
return ManagedPtr<Function>(range.first->second, &this->__functions);
}
std::list<ManagedFnPtr>
AST::getAllFunctions() const {
const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
for (size_t i = 0; i < size; ++i) {
result.push_back(ManagedFnPtr(i, &this->__functions));
}
return result;
}
//TASK select default specializations
std::list<ManagedFnPtr>
-AST::getFunctionSpecializations(const std::string& fnName) const {
- auto functions = __indexFunctions.equal_range(fnName);
+AST::getFnSpecializations(const std::string& fnName) const {
+ auto functions = __dictFunctions.equal_range(fnName);
std::list<ManagedFnPtr> result;
std::transform(functions.first, functions.second, inserter(result, result.end()),
[this](auto f) {
return ManagedFnPtr(f.second, &this->__functions);
});
return result;
}
template<>
ManagedPtr<Function>
AST::begin<Function>() {
return ManagedPtr<Function>(0, &this->__functions);
}
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>() {
return ManagedPtr<CodeScope>(0, &this->__scopes);
}
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>() {
return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
}
void
+AST::recognizeIntrinsic(Expression& fn) const {
+ assert(fn.op == Operator::CALL_INTRINSIC);
+ if (!__registryIntrinsics.count(fn.getValueString())){
+ assert(false);
+ }
+
+ IntrinsicFn fnCode = __registryIntrinsics.at(fn.getValueString());
+ fn.op = Operator::CALL_INTRINSIC;
+ fn.setValueDouble((int) fnCode);
+}
+
+bool
AST::recognizeVariantConstructor(Expression& function) {
assert(function.op == Operator::CALL);
-
std::string variant = function.getValueString();
- if (!__dictVariants.count(variant)) {
- return;
+ if (!__registryVariants.count(variant)) {
+ return false;
}
- auto record = __dictVariants.at(variant);
+ auto record = __registryVariants.at(variant);
const TypeAnnotation& typ = record.first;
function.op = Operator::VARIANT;
function.setValueDouble(record.second);
function.type = typ;
+ return true;
}
Atom<Number_t>
AST::recognizeVariantConstructor(Atom<Identifier_t> ident) {
std::string variant = ident.get();
- assert(__dictVariants.count(variant) && "Can't recognize variant constructor");
- auto record = __dictVariants.at(variant);
+ assert(__registryVariants.count(variant) && "Can't recognize variant constructor");
+ auto record = __registryVariants.at(variant);
return Atom<Number_t>(record.second);
}
void
AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
- bucketUnrecognizedIdentifiers.emplace(scope, id);
+ __bucketUnrecognizedIdentifiers.emplace(scope, id);
}
void
AST::recognizePostponedIdentifiers() {
- for (const auto& identifier : bucketUnrecognizedIdentifiers) {
+ for (const auto& identifier : __bucketUnrecognizedIdentifiers) {
if (!identifier.first->recognizeIdentifier(identifier.second)) {
//exception: Ident not found
- std::cout << "Unknown symbol: " << identifier.second.getValueString() << std::endl;
- assert(false && "Symbol not found");
+ std::cout << "Unknown identifier: " << identifier.second.getValueString() << std::endl;
+ assert(false && "Unknown identifier");
}
}
}
xreate::AST*
AST::finalize() {
//all finalization steps:
recognizePostponedIdentifiers();
return reinterpret_cast<xreate::AST*> (this);
}
+void
+AST::initIntrinsics(){
+ if (__registryIntrinsics.size()) return;
+
+ __registryIntrinsics = {
+ {"array_init", IntrinsicFn::ARR_INIT},
+ {"rec_fields", IntrinsicFn::REC_FIELDS}
+ };
+}
} } //namespace details::incomplete
Expanded<TypeAnnotation>
AST::findType(const std::string& name) {
// find in general scope:
- if (__indexTypeAliases.count(name))
- return expandType(__indexTypeAliases.at(name));
+ if (__registryTypes.count(name))
+ return expandType(__registryTypes.at(name));
//if type is unknown keep it as is.
- TypeAnnotation t(TypeOperator::CUSTOM,{});
+ TypeAnnotation t(TypeOperator::ALIAS, {});
t.__valueCustom = name;
return ExpandedType(move(t));
}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const {
- return TypesResolver(this)(t);
+ return TypeResolver(this, nullptr, {}, {})(t);
}
ExpandedType
-AST::getType(const Expression& expression) {
- return typeinference::getType(expression, *this);
+AST::getType(const Expression& e, const TypeAnnotation& expectedT) {
+ return typeinference::getType(e, expectedT, *this);
}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0)) {
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod) {
string name = tag.getValueString();
__tags.emplace(move(name), move(tag));
}
const std::map<std::string, Expression>&
Function::getTags() const {
return __tags;
}
CodeScope*
Function::getEntryScope() const {
return __entry;
}
void
Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument, const VNameId hintBindingId) {
__entry->addBinding(move(name), move(argument), hintBindingId);
}
const std::string&
Function::getName() const {
return __name;
}
ScopedSymbol
CodeScope::registerIdentifier(const Expression& identifier, const VNameId hintBindingId) {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
auto result = __identifiers.emplace(identifier.getValueString(), hintBindingId? hintBindingId: __identifiers.size() + 1);
return { result.first->second, version };
}
bool
CodeScope::recognizeIdentifier(const Expression& identifier) const {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
const std::string& name = identifier.getValueString();
//search identifier in the current block
if (__identifiers.count(name)) {
VNameId id = __identifiers.at(name);
Symbol s;
s.identifier = ScopedSymbol{id, version};
s.scope = const_cast<CodeScope*> (this);
Attachments::put<IdentifierSymbol>(identifier, s);
return true;
}
//search in the parent scope
if (__parent) {
return __parent->recognizeIdentifier(identifier);
}
return false;
}
ScopedSymbol
CodeScope::getSymbol(const std::string& alias) {
assert(__identifiers.count(alias));
VNameId id = __identifiers.at(alias);
return {id, versions::VERSION_NONE };
}
void
CodeScope::addBinding(Expression&& var, Expression&& argument, const VNameId hintBindingId) {
argument.__state = Expression::BINDING;
__bindings.push_back(var.getValueString());
ScopedSymbol binding = registerIdentifier(var, hintBindingId);
__declarations[binding] = move(argument);
}
Symbol
CodeScope::addDefinition(Expression&& var, Expression&& body) {
ScopedSymbol s = registerIdentifier(var);
__declarations[s] = move(body);
return Symbol{s, this};
}
CodeScope::CodeScope(CodeScope* parent)
: __parent(parent) {
}
CodeScope::~CodeScope() {
}
void
CodeScope::setBody(const Expression &body) {
assert(__declarations.count(ScopedSymbol::RetSymbol)==0 && "Attempt to reassign scope body");
__declarations[ScopedSymbol::RetSymbol] = body;
}
const Expression&
CodeScope::getBody() const{
return __declarations.at(ScopedSymbol::RetSymbol);
}
const Expression&
CodeScope::getDefinition(const Symbol& symbol, bool flagAllowUndefined){
const CodeScope* self = symbol.scope;
return self->getDefinition(symbol.identifier, flagAllowUndefined);
}
const Expression&
CodeScope::getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined) const{
static Expression expressionInvalid;
if (!__declarations.count(symbol)){
if (flagAllowUndefined) return expressionInvalid;
assert(false && "Symbol's declaration not found");
}
return __declarations.at(symbol);
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e) {
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards)) {
}
MetaRuleAbstract::~MetaRuleAbstract() {
}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
}
RuleWarning::~RuleWarning() {
}
void
RuleWarning::compile(TranscendLayer& layer) {
//TODO restore addRuleWarning
//layer.addRuleWarning(*this);
}
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id < s2.id) || (s1.id == s2.id && s1.version < s2.version);
}
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id == s2.id) && (s1.version == s2.version);
}
bool operator<(const Symbol& s1, const Symbol& s2) {
return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
bool operator==(const Symbol& s1, const Symbol& s2) {
return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
}
+bool operator< (const ASTSite& s1, const ASTSite& s2){
+ return s1.id < s2.id;
+}
+
bool operator<(const Expression&a, const Expression&b) {
if (a.__state != b.__state) return a.__state < b.__state;
assert(a.__state != Expression::INVALID);
switch (a.__state) {
case Expression::IDENT:
case Expression::STRING:
return a.getValueString() < b.getValueString();
case Expression::NUMBER:
return a.getValueDouble() < b.getValueDouble();
case Expression::COMPOUND:
{
assert(a.blocks.size() == 0);
assert(b.blocks.size() == 0);
if (a.op != b.op) {
return a.op < b.op;
}
bool flagAValid = ExpressionHints::isStringValueValid(a);
bool flagBValid = ExpressionHints::isStringValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueString() != b.getValueString()) {
return a.getValueString() < b.getValueString();
}
}
flagAValid = ExpressionHints::isDoubleValueValid(a);
flagBValid = ExpressionHints::isDoubleValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueDouble() != b.getValueDouble()) {
return a.getValueDouble() < b.getValueDouble();
}
}
if (a.operands.size() != b.operands.size()) {
return (a.operands.size() < b.operands.size());
}
for (size_t i = 0; i < a.operands.size(); ++i) {
bool result = a.operands[i] < b.operands[i];
if (result) return true;
}
return false;
}
case Expression::BINDING:
case Expression::INVALID:
assert(false);
}
return false;
}
bool
Expression::operator==(const Expression& other) const {
if (this->__state != other.__state) return false;
if (ExpressionHints::isStringValueValid(*this)) {
if (this->__valueS != other.__valueS) return false;
}
if (ExpressionHints::isDoubleValueValid(*this)) {
if (this->__valueD != other.__valueD) return false;
}
if (this->__state != Expression::COMPOUND) {
return true;
}
if (this->op != other.op) {
return false;
}
if (this->operands.size() != other.operands.size()) {
return false;
}
for (size_t i = 0; i<this->operands.size(); ++i) {
if (!(this->operands[i] == other.operands[i])) return false;
}
assert(!this->blocks.size());
assert(!other.blocks.size());
return true;
}
const ScopedSymbol
ScopedSymbol::RetSymbol = ScopedSymbol{0, versions::VERSION_NONE};
+Expression
+ASTSite::getDefinition() const{
+ if (Attachments::exists<ExprAlias_A>(id)){
+ const Symbol& siteS = Attachments::get<ExprAlias_A>(id);
+ return CodeScope::getDefinition(siteS, true);
+ }
+
+ return Attachments::get<ExprId_A>(id);
+}
} //end of namespace xreate
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 5fee1f6..391b46d 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,745 +1,750 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: ast.h
*/
/**
* \file ast.h
* \brief A syntax tree representation and related code
*
* \sa xreate::AST
*/
#ifndef AST_H
#define AST_H
#include "attachments.h"
+#include "utils.h"
-#include <vector>
-#include <stdlib.h>
#include <string>
#include <list>
+#include <vector>
+#include <map>
+#include <set>
#include <unordered_map>
#include <unordered_set>
-#include <climits>
-#include "utils.h"
#include <algorithm>
-
-namespace llvm {
- class Value;
-}
+#include <climits>
namespace xreate {
struct ScopedSymbol;
struct Symbol;
}
namespace std {
template<>
struct hash<xreate::ScopedSymbol> {
std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
template<>
struct equal_to<xreate::ScopedSymbol> {
bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
};
template<>
struct hash<xreate::Symbol> {
size_t operator()(xreate::Symbol const& s) const;
};
template<>
struct equal_to<xreate::Symbol> {
bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
};
}
namespace xreate {
struct String_t {
};
struct Identifier_t {
};
struct Number_t {
};
struct Type_t {
};
template<typename A>
class Atom {
};
//DEBT store line:col for all atoms/identifiers
template<> class
Atom<Identifier_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
template<>
class Atom<Number_t> {
public:
Atom(wchar_t* value);
Atom(int value);
double get()const;
private:
double __value;
};
template<>
class Atom<String_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
enum class TypePrimitive {
- Invalid, Bool, I8, I32, I64, Num, Int, Float, String
+ Invalid, Bool, I8, I32, I64, Int, Float, String
};
enum class TypeOperator {
- NONE, CALL, CUSTOM, VARIANT, LIST_ARRAY, LIST_RECORD, ACCESS, LINK, SLAVE
-};
-
-struct llvm_array_tag {
+ NONE, VOID, REF, ALIAS, VARIANT, ARRAY, RECORD, ACCESS, SLAVE, GUARD
};
struct struct_tag {
};
-const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
/**
* \brief A type representation to support type system
*
* The class represents type in a denormalized form, i.e. with no arguments and aliases substitution
* \sa AST::expandType()
*/
class TypeAnnotation {
public:
TypeAnnotation();
- TypeAnnotation(const Atom<Type_t>& typ);
TypeAnnotation(TypePrimitive typ);
- TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator<(const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
bool isValid() const;
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
- int conjuctionId = -1; //conjunction point id (relevant for recursive types)
- uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator {
- INVALID, UNDEF, ADD, SUB, MUL, DIV,
+ INVALID, UNDEF, AND, OR, ADD, SUB, MUL, DIV,
EQU, NE, NEG, LSS,
LSE, GTR, GTE, LIST,
- LIST_RANGE,
+ LIST_INDEX, LIST_RANGE,
CALL, CALL_INTRINSIC, QUERY, QUERY_LATE,
IMPL/* implication */, MAP,
- FOLD, INF, INDEX,
+ FOLD, FOLD_INF, INDEX,
IF, SWITCH, SWITCH_VARIANT, SWITCH_LATE,
CASE, CASE_DEFAULT, LOGIC_AND,
- CONTEXT_RULE, VARIANT, SEQUENCE
+ CONTEXT_RULE, VARIANT, SEQUENCE, UPDATE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
/**
* \brief AST node to represent a single instruction or an annotation
* \attention In case of any changes update \ref xreate::ExpressionHints auxiliary helper as well
*
* %Expression is a generic building block of syntax tree which is able to hold node data
* along with child nodes as operands.
*
* \note For types the %expression-like data structure \ref TypeAnnotation is used rather than Expression itself.
* \sa xreate::AST, xreate::TypeAnnotation
*/
struct Expression {
friend class CodeScope;
friend class TranscendLayer;
friend class CFAPass;
friend class ExpressionHints;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addTags(const std::list<Expression> tags) const;
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isValid() const;
bool isDefined() const;
bool operator==(const Expression& other) const;
/**
* \brief is it string, number, compound operation and so on
*/
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, BINDING
} __state = INVALID;
/**
* \brief Valid for compound State. Holds type of compound operator
*/
Operator op;
/**
* \brief Unique id to identify expression within syntax tree
*/
unsigned int id;
/**
* \brief Exact meaning depends on particular instruction
* \details As an example, named lists/structs hold field names in bindings
*/
std::vector<std::string> bindings;
- std::map<std::string, size_t> __indexBindings;
-
+
/**
* \brief Holds child instructions as arguments
*/
std::vector<Expression> operands;
/**
* \brief Holds type of instruction's result
*/
TypeAnnotation type;
/**
* \brief Holds additional annotations
*/
mutable std::map<std::string, Expression> tags;
/**
* \brief Child code blocks
* \details For example, If statement holds TRUE-branch as first and FALSE-branch as second block here
*/
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
static unsigned int nextVacantId;
};
bool operator<(const Expression&, const Expression&);
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom) {
std::string key = atom.get();
- this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier {
NONE, ASSERT, REQUIRE
};
enum class DomainAnnotation {
FUNCTION, VARIABLE
};
class RuleArguments : public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards : public std::vector<Expression> {
public:
void add(Expression&& e);
};
class TranscendLayer;
class LLVMLayer;
class MetaRuleAbstract {
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(TranscendLayer& layer) = 0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning : public MetaRuleAbstract {
friend class TranscendLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(TranscendLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VNameId;
namespace versions {
typedef int VariableVersion;
const VariableVersion VERSION_NONE = -2;
const VariableVersion VERSION_INIT = 0;
}
template<>
struct AttachmentsDict<versions::VariableVersion> {
typedef versions::VariableVersion Data;
static const unsigned int key = 6;
};
struct ScopedSymbol {
VNameId id;
versions::VariableVersion version;
static const ScopedSymbol RetSymbol;
};
struct Symbol {
ScopedSymbol identifier;
const CodeScope * scope;
};
+struct ASTSite {
+ unsigned int id;
+
+ Expression getDefinition() const;
+ //static Ast registerSite(const Expression& e);
+};
+
struct IdentifierSymbol{};
-struct SymbolAlias{};
+struct ExprAlias_A{};
+struct ExprId_A{};
template<>
struct AttachmentsDict<IdentifierSymbol> {
typedef Symbol Data;
static const unsigned int key = 7;
};
template<>
-struct AttachmentsDict<SymbolAlias> {
+struct AttachmentsDict<ExprAlias_A> {
typedef Symbol Data;
static const unsigned int key = 9;
};
+template<>
+struct AttachmentsDict<ExprId_A>{
+ typedef Expression Data;
+ static const unsigned int key = 12;
+};
+
typedef std::pair<Expression, TagModifier> Tag;
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
+bool operator< (const ASTSite& s1, const ASTSite& s2);
/**
* \brief AST node to represent a single code block/a scope of visibility
*
* Holds a single expression as a `body` along with set of variable assignments(declarations) used in body's expression.
* \sa xreate::AST
*/
class CodeScope {
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent = 0);
~CodeScope();
/** \brief Set expression as a body */
void setBody(const Expression& body);
/** \brief Returns current code scope body */
const Expression& getBody() const;
/** \brief Adds variable definition to be used in body as well as in other declarations */
Symbol addDefinition(Expression&& var, Expression&& body);
/** \brief Returns symbols' definition */
static const Expression& getDefinition(const Symbol& symbol, bool flagAllowUndefined = false);
const Expression& getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined = false) const;
/** \brief Adds variable defined elsewhere */
void addBinding(Expression&& var, Expression&& argument, const VNameId hintBindingId = 0);
std::vector<std::string> __bindings;
std::map<std::string, VNameId> __identifiers;
CodeScope* __parent;
//TODO move __definitions to SymbolsAttachments data
//NOTE: definition of return type has index 0
std::unordered_map<ScopedSymbol, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
ScopedSymbol registerIdentifier(const Expression& identifier, const VNameId hintBindingId = 0);
public:
bool recognizeIdentifier(const Expression& identifier) const;
ScopedSymbol getSymbol(const std::string& alias);
};
/**
* \brief AST node to represent a single function
*
* Holds an `__entry` entry code scope along with `guard` to denote the different specializations.
* \sa xreate::AST
*/
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
/**
* \brief Adds function arguments
*/
void addBinding(Atom <Identifier_t>&& name, Expression&& argument, const VNameId hintBindingId=0);
/**
* \brief Adds additional function annotations
*/
void addTag(Expression&& tag, const TagModifier mod);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
- bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
-
Expression guard;
-
+
private:
std::map<std::string, Expression> __tags;
};
class ExternData;
-struct ExternEntry {
- std::string package;
- std::vector<std::string> headers;
-};
-
typedef Expanded<TypeAnnotation> ExpandedType;
struct TypeInferred{};
template<>
struct AttachmentsDict<TypeInferred> {
typedef ExpandedType Data;
static const unsigned int key = 11;
};
enum ASTInterface {
CFA, DFA, Extern, Adhoc
};
struct FunctionSpecialization {
std::string guard;
size_t id;
};
struct FunctionSpecializationQuery {
std::unordered_set<std::string> context;
};
template<>
struct AttachmentsId<Expression>{
static unsigned int getId(const Expression& expression){
return expression.id;
}
};
template<>
struct AttachmentsId<Symbol>{
static unsigned int getId(const Symbol& s){
return s.scope->__declarations.at(s.identifier).id;
}
};
template<>
struct AttachmentsId<ManagedFnPtr>{
static unsigned int getId(const ManagedFnPtr& f){
const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
return AttachmentsId<Symbol>::getId(symbolFunction);
}
};
template<>
struct AttachmentsId<CodeScope*>{
static unsigned int getId(const CodeScope* scope){
const Symbol symbolScope{ScopedSymbol::RetSymbol, scope};
return AttachmentsId<Symbol>::getId(symbolScope);
}
};
template<>
struct AttachmentsId<unsigned int>{
static unsigned int getId(const unsigned int id){
return id;
}
};
-class TypesResolver;
+class TypeResolver;
+
+enum class IntrinsicFn {
+ ARR_INIT,
+ REC_FIELDS
+};
+
namespace details { namespace inconsistent {
/**
* \brief AST in an inconsistent form during construction
*
* Represents AST under construction(**inconsistent state**).
* \attention Clients should use rather xreate::AST unless client's code explicitly works with Syntax Tree during construction.
*
* Typically an instance is created by xreate::XreateManager only and filled out by the parser
* \sa xreate::XreateManager::prepare(std::string&&)
*/
class AST {
- friend class xreate::TypesResolver;
+ friend class xreate::TypeResolver;
public:
AST();
/**
* \brief Adds new function to AST
* \param f Function to register
*/
void add(Function* f);
/**
* \brief Adds new declarative rule to AST
* \param r Declarative Rule
*/
void add(MetaRuleAbstract* r);
/** \brief Registers new code block */
ManagedScpPtr add(CodeScope* scope);
/**
* \brief Add new type to AST
* @param t Type definition
* @param alias Typer name
*/
void add(TypeAnnotation t, Atom<Identifier_t> alias);
/** \brief Current module's name */
std::string getModuleName();
/**
* \brief Looks for function with given name
* \param name Function name to find
* \note Requires that only one function exists under given name
* \return Found function
*/
ManagedPtr<Function> findFunction(const std::string& name);
/** \brief Returns all function in AST */
std::list<ManagedFnPtr> getAllFunctions() const;
/**
* \brief Returns all specializations of a function with a given name
* \param fnName function to find
* \return list of found function specializations
*/
- std::list<ManagedFnPtr> getFunctionSpecializations(const std::string& fnName) const;
+ std::list<ManagedFnPtr> getFnSpecializations(const std::string& fnName) const;
/**
* \return First element in Functions/Scopes/Rules list depending on template parameter
* \tparam Target either Function or CodeScope or MetaRuleAbstract
*/
template<class Target>
ManagedPtr<Target> begin();
/**
* \brief Performs all necessary steps after AST is built
*
* Performs all finalization steps and moves AST into consistent state represented by xreate::AST
* \sa xreate::AST
* \return AST in consistent state
*/
xreate::AST* finalize();
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
-
- std::vector<ExternEntry> __externdata;
+
+ //std::list<ExternData> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
- FUNCTIONS_REGISTRY __indexFunctions;
+ FUNCTIONS_REGISTRY __dictFunctions;
protected:
- std::map<std::string, TypeAnnotation> __indexTypeAliases;
+ std::map<std::string, TypeAnnotation> __registryTypes;
public:
/**
* \brief Stores DFA scheme for later use by DFA Pass
*
* Treats expression as a DFA scheme and feeds to the DFA Pass later
* \param data DFA Scheme
* \sa xreate::DFAPass
*/
void addDFAData(Expression&& data);
/** \brief Stores data for later use by xreate::ExternLayer */
- void addExternData(ExternData&& data);
+ void addExternData(ExternData&& entry);
/**
* \brief Generalized function to store particular data for later use by particular pass
* \param interface Particular Interface
* \param data Particular data
*/
void addInterfaceData(const ASTInterface& interface, Expression&& data);
/**\name Symbols Recognition */
///@{
public:
//TODO revisit enums/variants, move to codescope
/**
* \brief Tries to find out whether expression is Variant constructor
*/
- void recognizeVariantConstructor(Expression& function);
+ bool recognizeVariantConstructor(Expression& function);
Atom<Number_t> recognizeVariantConstructor(Atom<Identifier_t> ident);
+ /**
+ * \brief Postpones unrecognized identifier for future second round of recognition
+ * \param scope Code block identifier is encountered
+ * \param id Identifier
+ */
+ void postponeIdentifier(CodeScope* scope, const Expression& id);
+ /** \brief Second round of identifiers recognition done right after AST is fully constructed */
+ void recognizePostponedIdentifiers();
+
+ void recognizeIntrinsic(Expression& fn) const;
private:
- std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
+ std::map<std::string, std::pair<TypeAnnotation, int>> __registryVariants;
+ static std::map<std::string, IntrinsicFn> __registryIntrinsics;
+ std::set<std::pair<CodeScope*, Expression>> __bucketUnrecognizedIdentifiers;
-public:
- std::set<std::pair<CodeScope*, Expression>> bucketUnrecognizedIdentifiers;
+ static void initIntrinsics();
public:
- /**
- * \brief Postpones unrecognized identifier for future second round of recognition
- * \param scope Code block identifier is encountered
- * \param id Identifier
- */
- void postponeIdentifier(CodeScope* scope, const Expression& id);
-
- /** \brief Second round of identifiers recognition done right after AST is fully constructed */
- void recognizePostponedIdentifiers();
+
///@}
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
} } // namespace details::incomplete
/**
* \brief AST in a consistent state
*
* AST has two mutually exclusive possible states:
* - an inconsistent state while AST is under construction. Represented by xreate::details::inconsistent::AST
* - a consistent state when AST is built and finalize() is invoked.
*
* This class represents a consistent state and should be used by clients unless client's code explicitly works with AST under construction.
* Consistent AST enables access to additional functions(such as type management).
* \sa xreate::details::inconsistent::AST
*/
class AST : public details::inconsistent::AST {
public:
AST() : details::inconsistent::AST() {}
/**
* \brief Computes fully expanded form of type by substituting all arguments and aliases
* \param t Type to expand
* \return Expdanded or normal form of type
* \sa TypeAnnotation
*/
ExpandedType expandType(const TypeAnnotation &t) const;
/**
* Searches type by given name
* \param name Typename to search
* \return Expanded or normal form of desired type
* \note if type name is not found returns new undefined type with this name
*/
ExpandedType findType(const std::string& name);
/**
* Invokes Type Inference Analysis to find out expanded(normal) form expressions's type
* \sa typeinference.h
- * \param expression
+ * \param e
+ * \param expectedT expected type
* \return Type of expression
*/
- ExpandedType getType(const Expression& expression);
+ ExpandedType getType(const Expression& e, const TypeAnnotation& expectedT = TypeAnnotation());
};
}
#endif // AST_H
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index 8ef3663..8b9c0cb 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,183 +1,184 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: attachments.h
* Date: 3/15/15
*/
/**
* \file attachments.h
* \brief The attachments support: a mechanism to attach additional data to AST nodes
*/
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <type_traits>
namespace xreate
{
/** \brief Attachments dictionary */
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
// static const unsigned int key (next vacant id - 12);
// Defined attachments:
//-----------------------------------------------------
// 1 containers::Implementation
// 3 interpretation::InterpretationData
-// 5 interpretation::FunctionInterpretationData
+// 5 interpretation::I12nFunctionSpec
// 6 VariableVersion
// 7 IdentifierSymbol
// 8 versions::VersionImposedDependency
-// 9 SymbolAlias
+// 9 ExprAlias_A
// 11 TypeInferred
+// 12 ExprId_A
};
template<class Object>
struct AttachmentsId{
//static unsigned int getId(const Object& object);
};
template<class Data>
class IAttachmentsContainer{
protected:
virtual bool __exists(const unsigned int object)=0;
virtual Data& __get(const unsigned int object)=0;
virtual void __put(const unsigned int object, Data data)=0;
public:
template<class Id>
bool exists(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __exists(id);
}
template<class Id>
Data& get(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __get(id);
}
template<class Id>
Data get(const Id& object, const Data& dataDefault){
unsigned int id = AttachmentsId<Id>::getId(object);
if (! __exists(id)){
return dataDefault;
}
return __get(id);
}
template<class Id>
void put(const Id& object, Data data){
unsigned int id = AttachmentsId<Id>::getId(object);
__put(id, data);
}
virtual ~IAttachmentsContainer(){};
};
template<class Data>
class AttachmentsContainerDefault: public IAttachmentsContainer<Data>{
private:
std::unordered_map<unsigned int, Data> __data;
virtual bool __exists(const unsigned int id){
return __data.count(id);
}
virtual Data& __get(const unsigned int id){
return __data.at(id);
}
virtual void __put(const unsigned int id, Data data){
auto result = __data.emplace(id, data);
assert(result.second);
}
public:
std::unordered_map<unsigned int, Data>& getRawStorage() {
return __data;
}
};
/** \brief Implements %AST attachments mechanism to facilitate data sharing among different analyzers and compilation phases */
class Attachments{
private:
static std::vector<void*> __storage;
template<class Tag>
using Data = typename AttachmentsDict<Tag>::Data;
public:
template<class Tag, class Id>
static bool exists(const Id& object) {
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->exists(object);
}
template<class Tag, class Id>
static Data<Tag>& get(const Id& object){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get(object);
}
template<class Tag, class Id>
static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get(object, dataDefault);
}
template<class Tag, class Id>
static void put(const Id& object, Data<Tag> data){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
self->put(object, data);
}
template<class Tag>
static void init(){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
}
template<class Tag>
static void init(IAttachmentsContainer<Data<Tag>>* container){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = container;
}
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/aux/expressions.cpp b/cpp/src/aux/expressions.cpp
new file mode 100644
index 0000000..67428a6
--- /dev/null
+++ b/cpp/src/aux/expressions.cpp
@@ -0,0 +1,60 @@
+#include "expressions.h"
+
+namespace xreate{
+
+Expression
+getVariantData(const Expression &variantE, ExpandedType variantT){
+ Expression result(Operator::LIST, {});
+ TypeAnnotation variantDataT(variantT->__operands.at(variantE.getValueDouble()));
+ if(!variantDataT.isValid()) return Expression();
+
+ assert(variantDataT.__operator == TypeOperator::RECORD);
+ result.operands = variantE.operands;
+ result.bindings = variantDataT.fields;
+ result.type = variantDataT;
+ return result;
+}
+
+ListDictionary
+reprListAsDict(const Expression &e){
+ ListDictionary result;
+ assert(e.__state == Expression::COMPOUND);
+
+ switch(e.op){
+ case Operator::LIST:{
+ Expression keyE;
+ int lastPos = 0;
+ for(size_t i = 0; i < e.operands.size(); ++i){
+ const Expression &valueE = e.operands.at(i);
+ const std::string &keyS = e.bindings.at(i);
+
+ if(keyS.empty()){
+ keyE = Expression(Atom<Number_t>(lastPos++));
+ } else{
+ keyE = Expression(Atom<String_t>(std::string(keyS)));
+ }
+
+ result.emplace(keyE, valueE);
+ }
+ break;
+ }
+
+ case Operator::LIST_INDEX:{
+ auto opI = e.operands.cbegin();
+ while(opI != e.operands.cend()){
+ const Expression &keysListE = *(opI++);
+ const Expression &valueE = *(opI++);
+ assert(keysListE.operands.size() == 1);
+
+ result.emplace(keysListE.operands.at(0), valueE);
+ }
+ break;
+ }
+ default:
+ assert(false);
+ }
+
+ return result;
+}
+
+}
\ No newline at end of file
diff --git a/cpp/src/aux/expressions.h b/cpp/src/aux/expressions.h
new file mode 100644
index 0000000..4be22b8
--- /dev/null
+++ b/cpp/src/aux/expressions.h
@@ -0,0 +1,15 @@
+//
+// Created by pgess on 31/01/2020.
+//
+
+#ifndef XREATE_EXPRESSIONS_H
+#define XREATE_EXPRESSIONS_H
+
+#include "ast.h"
+
+namespace xreate{
+ typedef std::map<Expression, Expression> ListDictionary;
+ Expression getVariantData(const Expression& variantE, ExpandedType variantT);
+ ListDictionary reprListAsDict(const Expression& e);
+}
+#endif //XREATE_EXPRESSIONS_H
diff --git a/cpp/src/aux/serialization/expressionserializer.cpp b/cpp/src/aux/serialization/expressionserializer.cpp
index e450529..4917f94 100644
--- a/cpp/src/aux/serialization/expressionserializer.cpp
+++ b/cpp/src/aux/serialization/expressionserializer.cpp
@@ -1,321 +1,321 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* expressionserializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "aux/serialization/expressionserializer.h"
#include <boost/utility.hpp>
#include <boost/utility/in_place_factory.hpp>
-
#include <cmath>
+#include <cstring>
using namespace std;
//using namespace boost::bimaps;
namespace xreate {
struct Index {
string name;
size_t degree; //count of parameters
unsigned char level; //level in expression tree (depth of tree layer)
bool operator< (const Index other) const{
if (name != other.name) return name < other.name;
if (degree != other.degree) return degree < other.degree;
if (name != other.name) return level < other.level;
return false;
}
};
class ExpressionSerializerPrivate {
//boost::bimap<Index, multiset_of<size_t>> __registry;
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::INVALID: {
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::INVALID: {
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(boost::in_place());
//move(PackedExpression())
strategy->pack(e, 0, result);
assert(result);
return move(*result);
}
OptionalPackedExpression
ExpressionSerializer::getIdOptional(const Expression& e) const{
OptionalPackedExpression result(boost::in_place());
//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 OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
assert(exprPacked);
return __registry.at(*exprPacked);
}
boost::optional<size_t>
ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{
const OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
if (!exprPacked){
return boost::none;
}
return __registry.at(*exprPacked);
}
const Expression&
ExpressionSerializerIntegral::get(size_t id) const{
return at(id);
}
void
PackedExpression::operator<< (const std::pair<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");
}
#if BOOST_VERSION <= 105500
PackedExpression::PackedExpression(const PackedExpression& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
}
#endif
PackedExpression::PackedExpression(PackedExpression&& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
other.__storage = nullptr;
}
bool
PackedExpression::operator==(const PackedExpression& other) const{
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) == 0 ;
}
return false;
}
bool
PackedExpression::operator<(const PackedExpression& other) const{
if (size < other.size) { return true; }
if (countRemainedBits < other.countRemainedBits) return true;
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) < 0 ;
}
return false;
}
bool
PackedExpression::operator!=(const PackedExpression& other) const{
return ! ((*this) == other);
}
PackedExpression::~PackedExpression() {
delete[] __storage;
}
//PackedExpression::PackedExpression (const PackedExpression& other)
// : size(other.size), countRemainedBits(other.countRemainedBits)
//{
// __storage = new char[size];
// std::memcpy (__storage, other.__storage, size);
//}
} /* namespace xreate */
diff --git a/cpp/src/aux/xreatemanager-decorators.cpp b/cpp/src/aux/xreatemanager-decorators.cpp
index 37ec862..caf685b 100644
--- a/cpp/src/aux/xreatemanager-decorators.cpp
+++ b/cpp/src/aux/xreatemanager-decorators.cpp
@@ -1,77 +1,86 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager-decorators.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 16, 2017, 4:40 PM
*/
/**
* \file xreatemanager-decorators.h
* \brief \ref xreate::XreateManager decorators to provide various functionality
*/
#include "aux/xreatemanager-decorators.h"
#include "main/Parser.h"
#include "pass/compilepass.h"
-#include "pass/cfapass.h"
-#include "pass/dfapass.h"
+#include "transcendlayer.h"
+#include "analysis/transcendtarget.h"
#include "pass/interpretationpass.h"
-#include "pass/versionspass.h"
-#include "pass/cfatemporalseqpass.h"
+
+#ifndef XREATE_CONFIG_MIN
+ #include "pass/cfapass.h"
+ #include "pass/dfapass.h"
+ #include "pass/versionspass.h"
+ #include "pass/cfatemporalseqpass.h"
+#endif
+
namespace xreate{
void
XreateManagerDecoratorBase::initPasses() { }
void
XreateManagerDecoratorBase::prepareCode(std::string&& code) {
grammar::main::Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
grammar::main::Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager::prepare(parser.root->finalize());
}
void
XreateManagerDecoratorBase::prepareCode(FILE* code){
grammar::main::Scanner scanner(code);
grammar::main::Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager::prepare(parser.root->finalize());
}
void
XreateManagerDecoratorBase::analyse() {
CompilePass::prepareQueries(transcend);
transcend->run();
}
void
XreateManagerDecoratorFull::initPasses() {
+ #ifndef XREATE_CONFIG_MIN
cfa::CFAPass* passCFG = new cfa::CFAPass(this);
-
registerPass(new dfa::DFAPass(this), PassId::DFAPass);
registerPass(passCFG, PassId::CFAPass);
- registerPass(new interpretation::InterpretationPass(this), PassId::InterpretationPass);
registerPass(new versions::VersionsPass(this), PassId::VersionsPass);
registerPass(new cfa::CFATemporalSeqPass(this), PassId::CFATemporalSeqPass);
+ #endif
+
+ registerPass(new interpretation::InterpretationPass(this), PassId::InterpretationPass);
+ registerPass(new TranscendPass(this), PassId::TranscendPass);
}
void*
XreateManagerDecoratorFull::run() {
transcend->deleteReports();
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<>(this));
compiler->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
} //namespace xreate
diff --git a/cpp/src/compilation/advancedinstructions.cpp b/cpp/src/compilation/advancedinstructions.cpp
deleted file mode 100644
index b6ca440..0000000
--- a/cpp/src/compilation/advancedinstructions.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * File: InstructionsAdvanced.cpp
- * Author: pgess <v.melnychenko@xreate.org>
- *
- * Created on June 26, 2016, 6:00 PM
- */
-
-#include "analysis/typeinference.h"
-#include "compilation/advancedinstructions.h"
-#include "compilation/containers.h"
-#include "compilation/transformersaturation.h"
-
-#include "query/containers.h"
-#include "llvmlayer.h"
-#include "ast.h"
-
-using namespace std;
-using namespace llvm;
-using namespace xreate;
-using namespace xreate::containers;
-using namespace xreate::compilation;
-
-#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
-#define UNUSED(x) (void)(x)
-#define EXPAND_CONTEXT \
- LLVMLayer* llvm = context.pass->man->llvm; \
- compilation::ICodeScopeUnit* scope = context.scope; \
- compilation::IFunctionUnit* function = context.function;
-
-AdvancedInstructions::AdvancedInstructions(compilation::Context ctx)
-: context(ctx), tyNum(static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num))))) {
-}
-
-llvm::Value*
-AdvancedInstructions::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
- EXPAND_CONTEXT UNUSED(scope);
-
- //initialization
- Symbol symbolIn = Attachments::get<IdentifierSymbol>(expr.getOperands()[0]);
-
- ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
- size_t size = implIn.size;
- CodeScope* scopeLoop = expr.blocks.front();
- std::string varEl = scopeLoop->__bindings[0];
-
- Iterator* it = Iterator::create(context, symbolIn);
- llvm::Value *rangeFrom = it->begin();
- llvm::Value *rangeTo = it->end();
-
- //definitions
- ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
- llvm::IRBuilder<> &builder = llvm->builder;
-
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "loop", function->raw);
- llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "postloop", function->raw);
- Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
-
- // * initial check
- Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
- builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
-
- // create PHI:
- builder.SetInsertPoint(blockLoop);
- llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
- stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
-
- // loop body:
- Value* elIn = it->get(stateLoop, varEl);
- compilation::ICodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
- scopeLoopUnit->bindArg(elIn, move(varEl));
- Value* elOut = scopeLoopUnit->compile();
- Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
- builder.CreateStore(elOut, pElOut);
-
- //next iteration preparing
- Value *stateLoopNext = builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
- stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
-
- //next iteration checks:
- Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
- builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
-
- //finalization:
- builder.SetInsertPoint(blockAfterLoop);
-
- return dataOut;
-}
-
-Value*
-AdvancedInstructions::compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string hintRetVar) {
- EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
-
- indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
- llvm::Value *pEl = llvm->builder.CreateGEP(aggregate, llvm::ArrayRef<llvm::Value *>(indexes));
- return llvm->builder.CreateLoad(pEl, NAME("el"));
-}
-
-Value*
-AdvancedInstructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx) {
- EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
-
- TypeUtils types(llvm);
- std::vector<std::string>&& fields = types.getStructFields(t);
-
- for (unsigned i = 0, size = fields.size(); i < size; ++i) {
- if (fields.at(i) == idx) {
- //dereference pointer
- if (types.isPointer(t)) {
- llvm::Value* addr = llvm->builder.CreateConstGEP2_32(nullptr, aggregate, 0, i);
- return llvm->builder.CreateLoad(addr);
- }
-
- return llvm->builder.CreateExtractValue(aggregate, llvm::ArrayRef<unsigned>{i});
- }
- }
-
- assert(false && "not found required struct field");
- return nullptr;
-}
-
-llvm::Value*
-AdvancedInstructions::compileFold(const Expression& fold, const std::string& hintRetVar) {
- EXPAND_CONTEXT
- assert(fold.op == Operator::FOLD);
-
- //initialization:
- Symbol varInSymbol = Attachments::get<IdentifierSymbol>(fold.getOperands()[0]);
- Implementation info = Query::queryImplementation(varInSymbol);
-
- Iterator* it = Iterator::create(context, varInSymbol);
- llvm::Value* rangeBegin = it->begin();
- llvm::Value* rangeEnd = it->end();
- llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
- std::string varIn = fold.getOperands()[0].getValueString();
- std::string varAccum = fold.bindings[1];
- std::string varEl = fold.bindings[0];
-
- llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
- std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
-
-
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold", function->raw);
- llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm->llvmContext, "fold_body", function->raw);
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold_after", function->raw);
- llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "fold_next", function->raw);
-
- llvm->builder.CreateBr(blockLoop);
-
- // * create phi
- llvm->builder.SetInsertPoint(blockLoop);
- llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, varAccum);
- accum->addIncoming(accumInit, blockBeforeLoop);
- llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
- itLoop->addIncoming(rangeBegin, blockBeforeLoop);
-
- // * loop checks
- Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
- llvm->builder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
-
- // * loop body
- llvm->builder.SetInsertPoint(blockLoopBody);
- CodeScope* scopeLoop = fold.blocks.front();
- compilation::ICodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
- Value* elIn = it->get(itLoop);
- loopUnit->bindArg(accum, move(varAccum));
- loopUnit->bindArg(elIn, move(varEl));
- Value* accumNext = loopUnit->compile();
-
- // * Loop saturation checks
- bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
- llvm::BasicBlock* blockSaturation = llvm->builder.GetInsertBlock();
- if (!flagSaturationTriggered){
- llvm->builder.CreateBr(blockNext);
- }
-
- // * computing next iteration state
- llvm->builder.SetInsertPoint(blockNext);
- Value *itLoopNext = it->advance(itLoop);
- accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
- itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
- llvm->builder.CreateBr(blockLoop);
-
- // * finalization:
- llvm->builder.SetInsertPoint(blockAfterLoop);
- if (!flagSaturationTriggered){
- return accum;
- }
-
- llvm::PHINode* result = llvm->builder.CreatePHI(accumInit->getType(), 2);
- result->addIncoming(accum, blockLoop);
- result->addIncoming(accumNext, blockSaturation);
- return result;
-}
-
-llvm::Value*
-AdvancedInstructions::compileFoldInf(const Expression& fold, const std::string& hintRetVar) {
- EXPAND_CONTEXT
- assert(fold.op == Operator::INF);
-
- std::string accumName = fold.bindings[0];
- llvm::Value* accumInit = scope->process(fold.getOperands()[0]);
-
- llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf", function->raw);
- llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_next", function->raw);
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_post", function->raw);
- std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
-
- llvm->builder.CreateBr(blockLoop);
-
- // * create phi
- llvm->builder.SetInsertPoint(blockLoop);
- llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, accumName);
- accum->addIncoming(accumInit, blockBeforeLoop);
-
- // * loop body
- CodeScope* scopeLoop = fold.blocks.front();
- compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
- unitLoop->bindArg(accum, move(accumName));
- Value* accumNext = unitLoop->compile();
-
- // * Loop saturation checks
- bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
- assert(flagSaturationTriggered);
-
- // * computing next iteration state
- llvm->builder.SetInsertPoint(blockNext);
- accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
- llvm->builder.CreateBr(blockLoop);
-
- // finalization:
- llvm->builder.SetInsertPoint(blockAfterLoop);
- return accumNext;
-}
-
-llvm::Value*
-AdvancedInstructions::compileIf(const Expression& exprIf, const std::string& hintRetVar) {
- EXPAND_CONTEXT
-
- const Expression& condExpr = exprIf.getOperands()[0];
- llvm::IRBuilder<>& builder = llvm->builder;
- assert(builder.GetInsertBlock() == scope->currentBlockRaw);
-
- //initialization:
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "ifAfter", function->raw);
- llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm->llvmContext, "ifTrue", function->raw);
- llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm->llvmContext, "ifFalse", function->raw);
-
- llvm::Value* cond = scope->process(condExpr);
-
- builder.SetInsertPoint(blockTrue);
- CodeScope* scopeTrue = exprIf.blocks.front();
- llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
- llvm::BasicBlock * blockTrueEnd = builder.GetInsertBlock();
- builder.CreateBr(blockEpilog);
-
- builder.SetInsertPoint(blockFalse);
- CodeScope* scopeFalse = exprIf.blocks.back();
- llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
- llvm::BasicBlock * blockFalseEnd = builder.GetInsertBlock();
- builder.CreateBr(blockEpilog);
-
- builder.SetInsertPoint(scope->currentBlockRaw);
- llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
-
- builder.SetInsertPoint(blockEpilog);
- llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 2, NAME("if"));
-
- ret->addIncoming(resultTrue, blockTrueEnd);
- ret->addIncoming(resultFalse, blockFalseEnd);
-
- return ret;
-}
-
-//TODO Switch: default variant no needed when all possible conditions are considered
-llvm::Value*
-AdvancedInstructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar) {
- EXPAND_CONTEXT UNUSED(function);
- AST* root = context.pass->man->root;
- llvm::IRBuilder<>& builder = llvm->builder;
- assert(exprSwitch.operands.size() >= 2);
- assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
-
- int countCases = exprSwitch.operands.size() - 1;
- llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
- builder.SetInsertPoint(blockEpilog);
- llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(exprSwitch));
- llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
- llvm::Type* typI8 = llvm::Type::getInt8Ty(llvm->llvmContext);
-
- builder.SetInsertPoint(blockProlog);
- llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
- llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm->llvmContext, "caseDefault", function->raw);
- llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(
- typeinference::doAutomaticTypeConversion(conditionSwitch, typI8, builder),
- blockDefault,
- countCases);
-
- for (int size = exprSwitch.operands.size(), i = 2; i < size; ++i) {
- llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(i), function->raw);
-
- llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
- builder.SetInsertPoint(blockCase);
- llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
- builder.CreateBr(blockEpilog);
-
- ret->addIncoming(resultCase, builder.GetInsertBlock());
- builder.SetInsertPoint(blockProlog);
- instructionSwitch->addCase(
- dyn_cast<llvm::ConstantInt>(
- typeinference::doAutomaticTypeConversion(condCase, typI8, builder)),
- blockCase);
- }
-
- //compile default block:
- builder.SetInsertPoint(blockDefault);
- CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
- llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
- builder.CreateBr(blockEpilog);
- ret->addIncoming(resultDefault, builder.GetInsertBlock());
- builder.SetInsertPoint(blockEpilog);
-
- return ret;
-}
-
-llvm::Value*
-AdvancedInstructions::compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar) {
- EXPAND_CONTEXT UNUSED(function);
- AST* root = context.pass->man->root;
- llvm::IRBuilder<>& builder = llvm->builder;
- llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
- const ExpandedType& typVariant = root->getType(exprSwitch.operands.at(0));
- llvm::Type* typVariantRaw = llvm->toLLVMType(typVariant);
-
- assert(typVariant->__operands.size() == exprSwitch.operands.size() - 1 && "Ill-formed Switch Variant");
-
- int casesCount = exprSwitch.operands.size();
- llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
- llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
- builder.SetInsertPoint(blockEpilog);
- llvm::Type* resultType = llvm->toLLVMType(root->getType(exprSwitch));
- llvm::PHINode *ret = builder.CreatePHI(resultType, casesCount, NAME("switch"));
-
- builder.SetInsertPoint(blockProlog);
- llvm::Value * conditionSwitchRaw = scope->process(exprSwitch.operands.at(0));
- llvm::Value* idRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({0}));
-
- //Dereference preparation
- const bool flagPrepareDerefence = std::any_of(typVariant->__operands.begin(), typVariant->__operands.end(), [](const TypeAnnotation& op){
- return op.isValid();
- });
-
- llvm::Value* addrAsStorage = nullptr;
- if (flagPrepareDerefence){
- assert(exprSwitch.bindings.size() && "Switch condition alias not found");
- llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
- llvm::Value* storageRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({1}));
- addrAsStorage = llvm->builder.CreateAlloca(typStorageRaw);
- llvm->builder.CreateStore(storageRaw, addrAsStorage);
- }
-
- llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(idRaw, nullptr, casesCount);
- llvm::BasicBlock* blockDefaultUndefined;
- std::list<CodeScope*>::const_iterator scopeCaseIt = exprSwitch.blocks.begin();
- for (int instancesSize = exprSwitch.operands.size()-1, instId = 0; instId < instancesSize; ++instId) {
- llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(instId), function->raw);
- builder.SetInsertPoint(blockCase);
- ICodeScopeUnit* unitCase = function->getScopeUnit(*scopeCaseIt);
- const ExpandedType& instType = ExpandedType(typVariant->__operands.at(instId));
-
- //Actual variant derefence
- if (instType->isValid()) {
- string identCondition = exprSwitch.bindings.front();
- llvm::Type* instTypeRaw = llvm->toLLVMType(instType);
- llvm::Value* addrAsInst = llvm->builder.CreateBitOrPointerCast(addrAsStorage, instTypeRaw->getPointerTo());
- llvm::Value* instRaw = llvm->builder.CreateLoad(instTypeRaw, addrAsInst);
- const Symbol& identSymb = unitCase->bindArg(instRaw, move(identCondition));
- Attachments::put<TypeInferred>(identSymb, instType);
- }
-
- llvm::Value* resultCase = function->getScopeUnit(*scopeCaseIt)->compile();
- builder.CreateBr(blockEpilog);
-
- ret->addIncoming(resultCase, blockDefaultUndefined = builder.GetInsertBlock());
- builder.SetInsertPoint(blockProlog);
- instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, exprSwitch.operands.at(instId+1).getValueDouble())), blockCase);
- ++scopeCaseIt;
- }
-
- instructionSwitch->setDefaultDest(blockDefaultUndefined);
- builder.SetInsertPoint(blockEpilog);
- return ret;
-}
-
-//TODO recognize cases to make const arrays/stored in global mem/stack alloced.
-llvm::Value*
-AdvancedInstructions::compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar) {
- EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
-
- AST* root = context.pass->man->root;
- const size_t& length = expr.getOperands().size();
- const Expression& expression = expr;
- llvm::Value* zero = ConstantInt::get(tyNum, 0);
- llvm::Value* one = ConstantInt::get(tyNum, 1);
-
- ExpandedType typAggrExpanded = root->getType(expression);
- assert(typAggrExpanded->__operator == TypeOperator::LIST_ARRAY);
- llvm::Type* typEl = llvm->toLLVMType(ExpandedType(typAggrExpanded->__operands[0]));
- ArrayType* typAggr = (ArrayType*) llvm::ArrayType::get(typEl, length);
- llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), length, false), hintRetVar);
-
- const std::vector<Expression>& operands = expression.getOperands();
- llvm::Value* addrOperand = llvm->builder.CreateGEP(typAggr, list, ArrayRef<Value *>(std::vector<Value*>{zero, zero}));
- llvm->builder.CreateStore(scope->process(operands.front()), addrOperand) ;
- for (auto i=++operands.begin(); i!=operands.end(); ++i){
- addrOperand = llvm->builder.CreateGEP(typEl, addrOperand, ArrayRef<Value *>(std::vector<Value*>{one}));
- llvm->builder.CreateStore(scope->process(*i), addrOperand) ;
- }
-
- return list;
-// Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
-// l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
-}
-
-llvm::Value*
-AdvancedInstructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar) {
- EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
-
- Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm->llvmContext));
- //ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
-
- /*
- std::vector<Constant *> chars;
- chars.reserve(size+1);
-
- for (size_t i=0; i< size; ++i){
- chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
- }
- chars[size] = ConstantInt::get(typI8, 0);
- */
-
- Value* rawData = ConstantDataArray::getString(llvm->llvmContext, data);
- Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 1, false));
- llvm->builder.CreateStore(rawData, rawPtrData);
- return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
-}
-
-llvm::Value*
-AdvancedInstructions::compileSequence(const Expression &expr){
- EXPAND_CONTEXT UNUSED(scope); UNUSED(llvm);
-
- llvm::Value* result;
- for(CodeScope* scope: expr.blocks){
- result = function->getScopeUnit(scope)->compile();
- }
-
- return result;
-}
-
-
diff --git a/cpp/src/compilation/containers.cpp b/cpp/src/compilation/containers.cpp
index eb6c3f5..6a50ca4 100644
--- a/cpp/src/compilation/containers.cpp
+++ b/cpp/src/compilation/containers.cpp
@@ -1,208 +1,262 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: containers.cpp
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file compilation/containers.h
* \brief Containers compilation support. See [Containers](/d/concepts/containers/) in the Xreate's documentation.
*/
#include "compilation/containers.h"
+#include "compilation/targetinterpretation.h"
+#include "aux/expressions.h"
+#include "compilation/containers/arrays.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
-
-Iterator*
-Iterator::create(xreate::compilation::Context context, const xreate::Symbol& var){
-
-const Implementation& data = Query::queryImplementation(var);
-
-switch(data.impl){
- case ON_THE_FLY:
- return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
-
- case SOLID:
- return new IteratorForward<SOLID>(context, var, data.extract<SOLID>());
-
- default: assert(true);
-}
-
-assert(false && "Unknown declaration");
-return nullptr;
-}
-
-llvm::Value*
-IteratorForward<ON_THE_FLY>::begin() {
- switch(sourceDecl.op) {
- case xreate::Operator::LIST:
- {
- sourceRawType = llvm::Type::getInt32Ty(llvm->llvmContext);
- return llvm::ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 0);
- };
-
- case xreate::Operator::LIST_RANGE:{
- assert(sourceDecl.operands.size()==2);
-
- llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
- sourceRawType = result->getType();
-
- return result;
- };
-
- default: break;
+using namespace xreate::interpretation;
+using namespace xreate::typehints;
+
+namespace xreate { namespace containers{
+
+IContainersIR *
+IContainersIR::create(const Expression &aggrE, const TypeAnnotation &expectedT, const compilation::Context &context){
+ ExpandedType aggrT = context.pass->man->root->getType(aggrE, expectedT);
+ Expression aggr2E;
+
+ if (aggrE.__state == Expression::IDENT && !aggrE.tags.size()){
+ Symbol aggrS = Attachments::get<IdentifierSymbol>(aggrE);
+ aggr2E = CodeScope::getDefinition(aggrS);
+ } else {
+ aggr2E = aggrE;
+ }
+
+ switch(aggr2E.op){
+ case Operator::LIST:{
+ typehints::Array aggrHint = typehints::getHint(
+ aggr2E, typehints::Array{aggr2E.operands.size()}
+ );
+
+ return new ArrayIR(context, aggrT, aggrHint);
}
- if (linkedlist){
- llvm::Value* result = sourceUnit->process(sourceDecl);
- sourceRawType = result->getType();
- return result;
- }
-
- assert(false);
-}
-
-llvm::Value*
-IteratorForward<ON_THE_FLY>::end(){
- switch(sourceDecl.op) {
- case xreate::Operator::LIST: {
- size_t idLast = sourceDecl.operands.size() - 1;
- return ConstantInt::get(sourceRawType, idLast);
- }
-
- case xreate::Operator::LIST_RANGE: {
- assert(sourceDecl.operands.size() == 2);
- llvm::Value* valueEndOfRange = sourceUnit->process(sourceDecl.operands.at(1));
- llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1);
-
- return llvm->builder.CreateAdd(valueEndOfRange, valueConstOne);
- };
+ default:
+ typehints::Array aggrHint = typehints::getHint(
+ aggr2E, typehints::Array{0}
+ );
+ assert(aggrHint.size != 0);
+ return new ArrayIR(context, aggrT, aggrHint);
+ }
- default: break;
- }
-
- //return null pointer
- if (linkedlist){
- return ConstantPointerNull::getNullValue(sourceRawType);
- }
-
- assert(false && "Unknown declaration");
- return nullptr;
+ assert(false);
+ return nullptr;
}
-llvm::Value*
-IteratorForward<ON_THE_FLY>::get(Value* index,const std::string& hintRetVar){
- const Expression& currentDecl = CodeScope::getDefinition(current);
-
- switch (currentDecl.op) {
- case xreate::Operator::LIST: {
- //TODO re check is it right scope(source) to compile currentDecl. Provide unittests.
- llvm::Value* currentValue = sourceUnit->processSymbol(current);
- return xreate::compilation::AdvancedInstructions(context).compileArrayIndex(currentValue, std::vector<Value *>{index});
- };
-
- case xreate::Operator::LIST_RANGE: {
- return index;
- };
-
- case xreate::Operator::MAP: {
- assert(currentDecl.getOperands().size()==1);
- assert(currentDecl.bindings.size());
- assert(currentDecl.blocks.size());
-
- CodeScope* scopeLoop = currentDecl.blocks.front();
- std::string varEl = currentDecl.bindings[0];
-
- const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl.getOperands()[0]);
- auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
-
- Value* elIn = it->get(index, varEl);
- compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
- unitLoop->bindArg(elIn, std::move(varEl));
- return unitLoop->compile();
- }
-
- case xreate::Operator::INVALID: {
- //TODO review iterator determination strategy for case of Expression::BINDING
- assert(currentDecl.__state==Expression::IDENT);
-
- const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl);
- auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
- return it->get(index);
- };
-
- default: break;
- }
-
- if (linkedlist){
- return index;
- }
-
- assert(false && "Unknown declaration");
- return nullptr;
+llvm::Value *
+RecordIR::init(llvm::StructType *tyAggr){
+ return llvm::UndefValue::get(tyAggr);
}
-llvm::Value*
-IteratorForward<ON_THE_FLY>::advance(Value* index, const std::string& hintRetVar){
- switch(sourceDecl.op)
- {
- case xreate::Operator::LIST:
- case xreate::Operator::LIST_RANGE:
- return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1), hintRetVar);
-
- default: break;
+llvm::Value *
+RecordIR::update(llvm::Value *aggrRaw, const ExpandedType &aggrT, const Expression &updE){
+ InterpretationScope *scopeI12n = __context.pass->targetInterpretation->transformContext(__context);
+ TypesHelper helper(__context.pass->man->llvm);
+ const auto &fields = helper.getRecordFields(aggrT);
+
+ std::map<std::string, size_t> indexFields;
+ for(size_t i = 0, size = fields.size(); i < size; ++i){
+ indexFields.emplace(fields[i], i);
+ }
+
+ for(const auto &entry: reprListAsDict(updE)){
+ unsigned keyId;
+ std::string keyHint;
+ const Expression keyE = scopeI12n->process(entry.first);
+
+ switch(keyE.__state){
+ case Expression::STRING:
+ keyId = indexFields.at(keyE.getValueString());
+ keyHint = keyE.getValueString();
+ break;
+
+ case Expression::NUMBER:
+ keyId = keyE.getValueDouble();
+ keyHint = aggrT->fields.at(keyId);
+ break;
+ default:
+ assert(false);
+ break;
}
- if (linkedlist){
- ExpandedType tySource = llvm->ast->getType(CodeScope::getDefinition(source));
- assert(tySource->__operator == TypeOperator::LIST_ARRAY && "Linked list implementation has to have ARRAY type");
- assert(tySource->__operands.size());
+ const TypeAnnotation &valueT = aggrT->__operands.at(keyId);
- return xreate::compilation::AdvancedInstructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
- }
+ llvm::Value *valueRaw = __context.scope->process(entry.second, keyHint, valueT);
+ aggrRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
+ aggrRaw,
+ valueRaw,
+ keyId);
+ }
- assert(false && "Unknown declaration");
- return nullptr;
+ return aggrRaw;
}
-//const ImplementationRec<ON_THE_FLY>& implementation
-
-IteratorForward<SOLID>::IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation)
- : Iterator(), __length(implementation.size), llvm(ctx.pass->man->llvm)
-{
- __container = ctx.function->getScopeUnit(symbolContainer.scope)->processSymbol(symbolContainer);
-}
-
-llvm::Value*
-IteratorForward<SOLID>::begin(){
- //0
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 0);
-}
-
-llvm::Value*
-IteratorForward<SOLID>::end(){
- //length
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), __length);
-}
-
-llvm::Value*
-IteratorForward<SOLID>::get(llvm::Value* index,const std::string& hintRetVar){
- //GEP[index]]
-
- llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
- llvm::Value* pResult = llvm->builder.CreateGEP(__container, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), index}));
- return llvm->builder.CreateLoad(pResult, hintRetVar);
-}
+//IFwdIteratorIR*
+//IFwdIteratorIR::create(xreate::compilation::Context context, const xreate::Symbol& var){
+// const Implementation& data = Query::queryImplementation(var);
+//
+// switch(data.impl){
+// case ON_THE_FLY:
+// return new FwdIteratorIR<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
+//
+// case SOLID:
+// return new FwdIteratorIR<SOLID>(context, var, data.extract<SOLID>());
+//
+// default: break;
+//}
+//
+// assert(false && "Unknown declaration");
+// return nullptr;
+//}
+//
+//llvm::Value*
+//FwdIteratorIR<ON_THE_FLY>::begin() {
+// switch(sourceDecl.op) {
+// case xreate::Operator::LIST:
+// {
+// sourceRawType = llvm::Type::getInt32Ty(llvm->llvmContext);
+// return llvm::ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 0);
+// };
+//
+// case xreate::Operator::LIST_RANGE:{
+// assert(sourceDecl.operands.size()==2);
+//
+// llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
+// sourceRawType = result->getType();
+//
+// return result;
+// };
+//
+// default: break;
+// }
+//
+// if (linkedlist){
+// llvm::Value* result = sourceUnit->process(sourceDecl);
+// sourceRawType = result->getType();
+// return result;
+// }
+//
+// assert(false);
+//}
+//
+//llvm::Value*
+//FwdIteratorIR<ON_THE_FLY>::end(){
+// switch(sourceDecl.op) {
+// case xreate::Operator::LIST: {
+// size_t idLast = sourceDecl.operands.size() - 1;
+// return ConstantInt::get(sourceRawType, idLast);
+// }
+//
+// case xreate::Operator::LIST_RANGE: {
+// assert(sourceDecl.operands.size() == 2);
+// llvm::Value* valueEndOfRange = sourceUnit->process(sourceDecl.operands.at(1));
+// llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1);
+//
+// return llvm->irBuilder.CreateAdd(valueEndOfRange, valueConstOne);
+// };
+//
+// default: break;
+// }
+//
+// //return null pointer
+// if (linkedlist){
+// return ConstantPointerNull::getNullValue(sourceRawType);
+// }
+//
+// assert(false && "Unknown declaration");
+// return nullptr;
+//}
+//
+//llvm::Value*
+//FwdIteratorIR<ON_THE_FLY>::get(Value* index, const std::string& hintRetVar){
+// const Expression& currentDecl = CodeScope::getDefinition(current);
+//
+// switch (currentDecl.op) {
+// case xreate::Operator::LIST: {
+// //TODO re check is it right scope(source) to compile currentDecl. Provide unittests.
+// llvm::Value* currentValue = sourceUnit->processSymbol(current);
+// return xreate::compilation::ControlIR(context).compileArrayIndex(currentValue, std::vector<Value *>{index});
+// };
+//
+// case xreate::Operator::LIST_RANGE: {
+// return index;
+// };
+//
+// case xreate::Operator::MAP: {
+// assert(currentDecl.getOperands().size()==1);
+// assert(currentDecl.bindings.size());
+// assert(currentDecl.blocks.size());
+//
+// CodeScope* scopeLoop = currentDecl.blocks.front();
+// std::string varEl = currentDecl.bindings[0];
+//
+// const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl.getOperands()[0]);
+// auto it = std::unique_ptr<IFwdIteratorIR>(IFwdIteratorIR::create(context, symbIn));
+//
+// Value* elIn = it->get(index, varEl);
+// compilation::IBruteScope* unitLoop = function->getScopeUnit(scopeLoop);
+// unitLoop->bindArg(elIn, std::move(varEl));
+// return unitLoop->compile();
+// }
+//
+// case xreate::Operator::INVALID: {
+// //TODO review iterator determination strategy for case of Expression::BINDING
+// assert(currentDecl.__state==Expression::IDENT);
+//
+// const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl);
+// auto it = std::unique_ptr<IFwdIteratorIR>(IFwdIteratorIR::create(context, symbIn));
+// return it->get(index);
+// };
+//
+// default: break;
+// }
+//
+// if (linkedlist){
+// return index;
+// }
+//
+// assert(false && "Unknown declaration");
+// return nullptr;
+//}
+//
+//llvm::Value*
+//FwdIteratorIR<ON_THE_FLY>::advance(Value* index, const std::string& hintRetVar){
+// switch(sourceDecl.op)
+// {
+// case xreate::Operator::LIST:
+// case xreate::Operator::LIST_RANGE:
+// return llvm->irBuilder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1), hintRetVar);
+//
+// default: break;
+// }
+//
+// if (linkedlist){
+// ExpandedType tySource = llvm->ast->getType(CodeScope::getDefinition(source));
+// assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
+// assert(tySource->__operands.size());
+//
+// return xreate::compilation::ControlIR(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), {linkedlist.fieldPointer});
+// }
+//
+// assert(false && "Unknown declaration");
+// return nullptr;
+//}
-llvm::Value*
-IteratorForward<SOLID>::advance(llvm::Value* index, const std::string& hintRetVar){
- //index + 1
+//const ImplementationRec<ON_THE_FLY>& implementation
- llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
- return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(tyNum, 1), hintRetVar);
-}
+}} //end of xreate::containers
diff --git a/cpp/src/compilation/containers.h b/cpp/src/compilation/containers.h
index 893b387..4e830e8 100644
--- a/cpp/src/compilation/containers.h
+++ b/cpp/src/compilation/containers.h
@@ -1,100 +1,103 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: containers.h
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
-#include "compilation/advancedinstructions.h"
+#include "compilation/control.h"
#include "query/containers.h"
+#include "analysis/typehints.h"
-namespace xreate {
- namespace containers {
+namespace xreate { namespace containers {
-using namespace llvm;
+class IFwdIteratorIR;
-/**
+class IContainersIR{
+public:
+ static IContainersIR *create(
+ const Expression &aggrE,
+ const TypeAnnotation &expectedT,
+ const compilation::Context &context);
+
+ virtual llvm::Value *init(const std::string &hintAlias = "") = 0;
+ virtual llvm::Value *update(llvm::Value *aggrRaw, const Expression &updE, const std::string &hintAlias) = 0;
+ virtual IFwdIteratorIR* getFwdIterator() = 0;
+ virtual ~IContainersIR(){}
+};
+
+class RecordIR{
+public:
+ RecordIR(const compilation::Context& context): __context(context){}
+ llvm::Value* init(llvm::StructType* tyAggr);
+ llvm::Value* update(llvm::Value* aggrRaw, const ExpandedType& aggrT, const Expression& updE);
+
+private:
+ compilation::Context __context;
+};
+
+/**
* \brief A factory to create a concrete iterator based on the solution provided by xreate::containers::Query
* \sa xreate::containers::Query
*/
-class Iterator{
+class IFwdIteratorIR{
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(){};
+ virtual ~IFwdIteratorIR(){};
- static Iterator* create(xreate::compilation::Context context, const xreate::Symbol& var);
+ virtual llvm::Value* begin() = 0;
+ virtual llvm::Value* end() = 0;
+ virtual llvm::Value* get(llvm::Value* aggrRaw, llvm::Value *idxRaw, const std::string &hintRetVar="") = 0;
+ virtual llvm::Value* advance(llvm::Value* idxRaw, const std::string& hintAlias="") = 0;
};
template<ImplementationType I>
-class IteratorForward;
+class FwdIteratorIR;
/** \brief The lazy container implementation.
*
* Represents computation on the fly.
- * \sa xreate::containers::Iterator, \sa xreate::containers::Query
+ * \sa xreate::containers::IFwdIteratorIR, \sa xreate::containers::Query
*/
-template<>
-class IteratorForward<ON_THE_FLY> : public Iterator {
-private:
- LLVMLayer* llvm;
- const xreate::Symbol current;
- const Symbol source;
- const ImplementationLinkedList linkedlist;
- const CodeScope* const sourceScope;
- //TODO initialize and mark as const (three fields)
- compilation::ICodeScopeUnit* sourceUnit;
- compilation::IFunctionUnit* function; //TODO is used somewhere?
- const Expression& sourceDecl;
- compilation::Context context;
- llvm::Type* sourceRawType =nullptr;
-
-public:
- IteratorForward(const compilation::Context& ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
- : llvm(ctx.pass->man->llvm),
- current(s),
- source(implementation.source),
- linkedlist(source),
- sourceScope(source.scope),
- sourceUnit(ctx.function->getScopeUnit(source.scope)),
- sourceDecl(CodeScope::getDefinition(source)),
- context(ctx)
- {}
-
- llvm::Value* begin() override;
- llvm::Value* end() override;
- llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
- llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
-};
-
-/** \brief The contiguous container implementation.
- *
- * Represents contiguous in memory(array) implementation.
- * \sa xreate::containers::Iterator, \sa xreate::containers::Query
- */
-template<>
-class IteratorForward<SOLID>: public Iterator{
- size_t __length;
- llvm::Value* __container;
- LLVMLayer* llvm;
-
-public:
- IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation);
- llvm::Value* begin() override;
- llvm::Value* end() override;
- llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
- llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
-};
+//template<>
+//class FwdIteratorIR<ON_THE_FLY> : public IFwdIteratorIR {
+//private:
+// LLVMLayer* llvm;
+// const xreate::Symbol current;
+// const Symbol source;
+// const ImplementationLinkedList linkedlist;
+// const CodeScope* const sourceScope;
+// //TODO initialize and mark as const (three fields)
+// compilation::IBruteScope* sourceUnit;
+// compilation::IBruteFunction* function; //TODO is used somewhere?
+// const Expression& sourceDecl;
+// compilation::Context context;
+// llvm::Type* sourceRawType =nullptr;
+//
+//public:
+// FwdIteratorIR(const compilation::Context& ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
+// : llvm(ctx.pass->man->llvm),
+// current(s),
+// source(implementation.source),
+// linkedlist(source),
+// sourceScope(source.scope),
+// sourceUnit(ctx.function->getScopeUnit(source.scope)),
+// sourceDecl(CodeScope::getDefinition(source)),
+// context(ctx)
+// {}
+//
+// llvm::Value* begin() override;
+// llvm::Value* end() override;
+// llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
+// llvm::Value* advance(llvm::Value* idxRaw, const std::string& hintAlias="") override;
+//};
}}
#endif //CODEINSTRUCTIONS_H
diff --git a/cpp/src/compilation/containers/arrays.cpp b/cpp/src/compilation/containers/arrays.cpp
new file mode 100644
index 0000000..ea287bd
--- /dev/null
+++ b/cpp/src/compilation/containers/arrays.cpp
@@ -0,0 +1,106 @@
+//
+// Created by pgess on 27/03/2020.
+//
+
+#include "compilation/containers/arrays.h"
+#include "aux/expressions.h"
+
+using namespace std;
+using namespace llvm;
+
+namespace xreate { namespace containers{
+
+llvm::ArrayType*
+ArrayIR::getRawT(){
+ assert(__aggrT->__operator == TypeOperator::ARRAY);
+ assert(__aggrT->__operands.size() == 1);
+
+ LLVMLayer* llvm = __context.pass->man->llvm;
+ llvm::Type* elRawT = llvm->toLLVMType(ExpandedType(__aggrT->__operands.at(0)));
+
+ return llvm::ArrayType::get(elRawT, __hints.size);
+}
+
+llvm::Value*
+ArrayIR::init(const string& hintAlias){
+ LLVMLayer* llvm = __context.pass->man->llvm;
+ TypesHelper helper(llvm);
+ llvm::ArrayType* aggrRawT = getRawT();
+
+ //llvm::Value* aggrLengthRaw = ConstantInt::get(helper.getPreferredIntTy(), aggrInfo.size);
+ llvm::Value* aggrRaw = llvm->irBuilder.CreateAlloca(aggrRawT, nullptr, hintAlias);
+
+ return aggrRaw;
+}
+
+llvm::Value*
+ArrayIR::update(llvm::Value* aggrRaw, const Expression& updE, const std::string& hintAlias) {
+ LLVMLayer* llvm = __context.pass->man->llvm;
+ TypesHelper helper(llvm);
+ llvm::IntegerType* intT = helper.getPreferredIntTy();
+ llvm::Value* idxZeroRaw = ConstantInt::get(intT, 0);
+ llvm::ArrayType* aggrRawT = getRawT();
+ const TypeAnnotation& elT = __aggrT->__operands.at(0);
+ //llvm::Type* elTRaw = llvm->toLLVMType(ExpandedType(aggrT->__operands.at(0)));
+
+ for (const auto& entry: reprListAsDict(updE)){
+ llvm::Value* keyRaw = __context.scope->process(entry.first);
+ llvm::Value* elRaw = __context.scope->process(entry.second, "", elT);
+
+ llvm::Value* elLoc = llvm->irBuilder.CreateGEP(
+ aggrRawT, aggrRaw, ArrayRef<llvm::Value*>(std::vector<Value*>{idxZeroRaw, keyRaw}));
+ llvm->irBuilder.CreateStore(elRaw, elLoc) ;
+ }
+
+ return aggrRaw;
+}
+
+llvm::Value*
+ArrayIR::get(llvm::Value* aggrRaw, std::vector<llvm::Value *> idxL, const std::string& hintAlias) {
+ LLVMLayer* llvm = __context.pass->man->llvm;
+ TypesHelper helper(llvm);
+ llvm::IntegerType* intT = helper.getPreferredIntTy();
+ llvm::Value* zeroRaw = ConstantInt::get(intT, 0);
+
+ idxL.insert(idxL.begin(), zeroRaw);
+ llvm::Value *pEl = llvm->irBuilder.CreateGEP(aggrRaw, llvm::ArrayRef<llvm::Value *>(idxL));
+ return llvm->irBuilder.CreateLoad(pEl, hintAlias);
+}
+
+IFwdIteratorIR* ArrayIR::getFwdIterator(){
+ return new FwdIteratorIR<SOLID>(this);
+}
+
+llvm::Value *
+FwdIteratorIR<SOLID>::begin(){
+ TypesHelper helper(__arraysIR->__context.pass->man->llvm);
+ llvm::IntegerType* intT = helper.getPreferredIntTy();
+
+ return llvm::ConstantInt::get(intT, 0);
+}
+
+llvm::Value *
+FwdIteratorIR<SOLID>::end(){
+ TypesHelper helper(__arraysIR->__context.pass->man->llvm);
+ llvm::IntegerType* intT = helper.getPreferredIntTy();
+ size_t size = __arraysIR->__hints.size;
+
+ return llvm::ConstantInt::get(intT, size);
+}
+
+llvm::Value *
+FwdIteratorIR<SOLID>::get(llvm::Value* aggrRaw, llvm::Value *idxRaw, const std::string &hintAlias){
+ return __arraysIR->get(aggrRaw, {idxRaw}, hintAlias);
+}
+
+llvm::Value *
+FwdIteratorIR<SOLID>::advance(llvm::Value *idxRaw, const std::string &hintAlias){
+ LLVMLayer* llvm = __arraysIR->__context.pass->man->llvm;
+ TypesHelper helper(llvm);
+ llvm::IntegerType* intT = helper.getPreferredIntTy();
+ llvm::Value* cnstOneRaw = llvm::ConstantInt::get(intT, 1);
+
+ return llvm->irBuilder.CreateAdd(idxRaw, cnstOneRaw, hintAlias);
+}
+
+}} //xreate::containers
\ No newline at end of file
diff --git a/cpp/src/compilation/containers/arrays.h b/cpp/src/compilation/containers/arrays.h
new file mode 100644
index 0000000..3401940
--- /dev/null
+++ b/cpp/src/compilation/containers/arrays.h
@@ -0,0 +1,53 @@
+//
+// Created by pgess on 27/03/2020.
+//
+
+#ifndef XREATE_ARRAYSIR_H
+#define XREATE_ARRAYSIR_H
+
+#include "compilation/containers.h"
+
+namespace xreate { namespace containers{
+
+class ArrayIR;
+
+/** \brief The contiguous container implementation.
+ *
+ * Represents contiguous in memory(array) implementation.
+ * \sa xreate::containers::IFwdIteratorIR, \sa xreate::containers::Query
+ */
+template<>
+class FwdIteratorIR<SOLID>: public IFwdIteratorIR {
+ ArrayIR* __arraysIR;
+
+public:
+ FwdIteratorIR(ArrayIR* arraysIR): __arraysIR(arraysIR) {};
+
+ virtual llvm::Value* begin() override;
+ virtual llvm::Value* end() override;
+ virtual llvm::Value* get(llvm::Value* aggrRaw, llvm::Value *idxRaw, const std::string &hintRetVar="") override;
+ virtual llvm::Value* advance(llvm::Value* idxRaw, const std::string& hintAlias="") override;
+};
+
+class ArrayIR : public IContainersIR{
+ friend class FwdIteratorIR<SOLID>;
+
+public:
+ ArrayIR(const compilation::Context &context, const ExpandedType &aggrT, const typehints::Array &hints)
+ : __context(context), __aggrT(aggrT), __hints(hints){}
+
+ virtual llvm::Value *init(const std::string &hintAlias = "") override;
+ virtual llvm::Value *update(llvm::Value *aggrRaw, const Expression &updE, const std::string &hintAlias) override;
+ virtual IFwdIteratorIR* getFwdIterator() override;
+ llvm::Value *get(llvm::Value *aggrRaw, std::vector<llvm::Value *> idxL, const std::string &hintAlias);
+ llvm::ArrayType *getRawT();
+
+private:
+ compilation::Context __context;
+ ExpandedType __aggrT;
+ typehints::Array __hints;
+};
+
+}} // xreate::containers
+
+#endif //XREATE_ARRAYSIR_H
diff --git a/cpp/src/compilation/control.cpp b/cpp/src/compilation/control.cpp
new file mode 100644
index 0000000..c300b7e
--- /dev/null
+++ b/cpp/src/compilation/control.cpp
@@ -0,0 +1,441 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * File: InstructionsAdvanced.cpp
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on June 26, 2016, 6:00 PM
+ */
+
+#include "analysis/typeinference.h"
+#include "compilation/control.h"
+#include "compilation/containers.h"
+#include "compilation/transformersaturation.h"
+
+#include "query/containers.h"
+#include "llvmlayer.h"
+#include "ast.h"
+
+using namespace std;
+using namespace llvm;
+using namespace xreate;
+using namespace xreate::containers;
+using namespace xreate::compilation;
+
+#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
+#define UNUSED(x) (void)(x)
+#define EXPAND_CONTEXT \
+ LLVMLayer* llvm = context.pass->man->llvm; \
+ compilation::IBruteScope* scope = context.scope; \
+ compilation::IBruteFunction* function = context.function;
+
+ControlIR::ControlIR(compilation::Context ctx)
+: context(ctx), tyNum(static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Int))))) {
+}
+
+llvm::Value*
+ControlIR::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
+ assert(false); return nullptr;
+ EXPAND_CONTEXT UNUSED(scope);
+
+// //initializationcompileListAsSolidArray
+// Symbol symbolIn = Attachments::get<IdentifierSymbol>(expr.getOperands()[0]);
+//
+// ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
+// size_t size = implIn.size;
+// CodeScope* scopeLoop = expr.blocks.front();
+// std::string varEl = scopeLoop->__bindings[0];
+//
+// IFwdIteratorIR* it = IFwdIteratorIR::create(context, symbolIn);
+// llvm::Value *rangeFrom = it->begin();
+// llvm::Value *rangeTo = it->end();
+//
+// //definitions
+// ArrayType* tyNumArray = nullptr; //(ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Int, size))));
+// llvm::IRBuilder<> &builder = llvm->irBuilder;
+//
+// llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "loop", function->raw);
+// llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
+// llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "postloop", function->raw);
+// Value* dataOut = llvm->irBuilder.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::IBruteScope* scopeLoopUnit = function->getScopeUnit(scopeLoop);
+// scopeLoopUnit->bindArg(elIn, move(varEl));
+// Value* elOut = scopeLoopUnit->compile();
+// Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
+// builder.CreateStore(elOut, pElOut);
+//
+// //next iteration preparing
+// Value *stateLoopNext = builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
+// stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
+//
+// //next iteration checks:
+// Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
+// builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
+//
+// //finalization:
+// builder.SetInsertPoint(blockAfterLoop);
+//
+// return dataOut;
+}
+
+Value*
+ControlIR::compileStructIndex(llvm::Value* aggregate, ExpandedType aggrT, const list<string>& indices) {
+ EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
+ TypesHelper types(llvm);
+ llvm::Value* result = aggregate;
+ assert(indices.size());
+
+ for (const string& indexField: indices){
+ const std::vector<std::string>& tyfields = types.getRecordFields(aggrT);
+ unsigned idx = -1; bool flagFound = false;
+ for (unsigned i = 0, size = tyfields.size(); i < size; ++i) {
+ if (tyfields.at(i) == indexField) {
+ idx = i; flagFound = true; break;
+ }
+ }
+
+ if (flagFound){
+ result = llvm->irBuilder.CreateExtractValue(result, llvm::ArrayRef<unsigned>{idx});
+ aggrT = typeinference::getSubtype(aggrT, indexField);
+ } else {
+ assert(false && "not found required struct field");
+ }
+ }
+
+ return result;
+
+//dereference pointer
+//if (types.isPointerT(t)) {
+// llvm::Value* addr = llvm->irBuilder.CreateConstGEP2_32(nullptr, aggregate, 0, i);
+// return llvm->irBuilder.CreateLoad(addr);
+//}
+}
+
+llvm::Value*
+ControlIR::compileFold(const Expression& loopE, const std::string& hintAlias) {
+ EXPAND_CONTEXT
+ assert(loopE.op == Operator::FOLD);
+ AST* ast = context.pass->man->root;
+
+ //initialization:
+ const Expression aggrE = loopE.getOperands().at(0);
+ llvm::Value* aggrRaw = context.scope->process(aggrE);
+ std::unique_ptr<IContainersIR> containerIR(IContainersIR::create(aggrE, TypeAnnotation(), context));
+ IFwdIteratorIR* aggrItIR = containerIR->getFwdIterator();
+ llvm::Value* idxBeginRaw = aggrItIR->begin();
+ llvm::Value* idxEndRaw = aggrItIR->end();
+ ExpandedType loopT = ast->getType(loopE);
+ std::string elAlias = loopE.bindings[0];
+ std::string accumAlias = loopE.bindings[1];
+ const Expression& accumE = loopE.getOperands().at(1);
+ ExpandedType accumT = ast->getType(accumE, loopT.get());
+ llvm::Type* accumRawT = llvm->toLLVMType(accumT);
+ llvm::Value* accumInitRaw = scope->process(accumE, accumAlias, accumT.get());
+
+ llvm::BasicBlock *blockBeforeLoop = llvm->irBuilder.GetInsertBlock();
+ std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
+
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold", function->raw);
+ llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm->llvmContext, "fold_body", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold_after", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "fold_next", function->raw);
+
+ llvm->irBuilder.CreateBr(blockLoop);
+
+ // * create phi
+ llvm->irBuilder.SetInsertPoint(blockLoop);
+ llvm::PHINode *accum = llvm->irBuilder.CreatePHI(accumRawT, 2, accumAlias);
+ accum->addIncoming(accumInitRaw, blockBeforeLoop);
+ llvm::PHINode *idxCurrentRaw = llvm->irBuilder.CreatePHI(idxBeginRaw->getType(), 2, "foldIt");
+ idxCurrentRaw->addIncoming(idxBeginRaw, blockBeforeLoop);
+
+ // * loop checks
+ Value* condRange = llvm->irBuilder.CreateICmpNE(idxCurrentRaw, idxEndRaw);
+ llvm->irBuilder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
+
+ // * loop body
+ llvm->irBuilder.SetInsertPoint(blockLoopBody);
+ CodeScope* scopeLoop = loopE.blocks.front();
+ compilation::IBruteScope* loopUnit = function->getScopeUnit(scopeLoop);
+ Value* elIn = aggrItIR->get(aggrRaw, idxCurrentRaw);
+ loopUnit->bindArg(accum, move(accumAlias));
+ loopUnit->bindArg(elIn, move(elAlias));
+ Value* accumNext = loopUnit->compile();
+
+ // * Loop saturation checks
+ bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
+ llvm::BasicBlock* blockSaturation = llvm->irBuilder.GetInsertBlock();
+ if (!flagSaturationTriggered){
+ llvm->irBuilder.CreateBr(blockNext);
+ }
+
+ // * computing next iteration state
+ llvm->irBuilder.SetInsertPoint(blockNext);
+ Value *itLoopNext = aggrItIR->advance(idxCurrentRaw);
+ accum->addIncoming(accumNext, llvm->irBuilder.GetInsertBlock());
+ idxCurrentRaw->addIncoming(itLoopNext, llvm->irBuilder.GetInsertBlock());
+ llvm->irBuilder.CreateBr(blockLoop);
+
+ // * finalization:
+ llvm->irBuilder.SetInsertPoint(blockAfterLoop);
+ if (!flagSaturationTriggered){
+ return accum;
+ }
+
+ llvm::PHINode* result = llvm->irBuilder.CreatePHI(accumRawT, 2, hintAlias);
+ result->addIncoming(accum, blockLoop);
+ result->addIncoming(accumNext, blockSaturation);
+
+ return result;
+}
+
+llvm::Value*
+ControlIR::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->irBuilder.GetInsertBlock();
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_next", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_post", function->raw);
+ std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
+
+ llvm->irBuilder.CreateBr(blockLoop);
+
+ // * create phi
+ llvm->irBuilder.SetInsertPoint(blockLoop);
+ llvm::PHINode *accum = llvm->irBuilder.CreatePHI(accumInit->getType(), 2, accumName);
+ accum->addIncoming(accumInit, blockBeforeLoop);
+
+ // * loop body
+ CodeScope* scopeLoop = fold.blocks.front();
+ compilation::IBruteScope* unitLoop = function->getScopeUnit(scopeLoop);
+ unitLoop->bindArg(accum, move(accumName));
+ Value* accumNext = unitLoop->compile();
+
+ // * Loop saturation checks
+ bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
+ assert(flagSaturationTriggered);
+
+ // * computing next iteration state
+ llvm->irBuilder.SetInsertPoint(blockNext);
+ accum->addIncoming(accumNext, llvm->irBuilder.GetInsertBlock());
+ llvm->irBuilder.CreateBr(blockLoop);
+
+ // finalization:
+ llvm->irBuilder.SetInsertPoint(blockAfterLoop);
+ return accumNext;
+}
+
+llvm::Value*
+ControlIR::compileIf(const Expression& exprIf, const std::string& hintRetVar) {
+ EXPAND_CONTEXT
+
+ const Expression& condExpr = exprIf.getOperands()[0];
+ llvm::IRBuilder<>& builder = llvm->irBuilder;
+ assert(builder.GetInsertBlock() == scope->currentBlockRaw);
+
+ //initialization:
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "ifAfter", function->raw);
+ llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm->llvmContext, "ifTrue", function->raw);
+ llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm->llvmContext, "ifFalse", function->raw);
+
+ llvm::Value* cond = scope->process(condExpr);
+
+ builder.SetInsertPoint(blockTrue);
+ CodeScope* scopeTrue = exprIf.blocks.front();
+ llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
+ llvm::BasicBlock * blockTrueEnd = builder.GetInsertBlock();
+ builder.CreateBr(blockEpilog);
+
+ builder.SetInsertPoint(blockFalse);
+ CodeScope* scopeFalse = exprIf.blocks.back();
+ llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
+ llvm::BasicBlock * blockFalseEnd = builder.GetInsertBlock();
+ builder.CreateBr(blockEpilog);
+
+ builder.SetInsertPoint(scope->currentBlockRaw);
+ llvm->irBuilder.CreateCondBr(cond, blockTrue, blockFalse);
+
+ builder.SetInsertPoint(blockEpilog);
+ llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 2, NAME("if"));
+
+ ret->addIncoming(resultTrue, blockTrueEnd);
+ ret->addIncoming(resultFalse, blockFalseEnd);
+
+ return ret;
+}
+
+//TODO Switch: default variant no needed when all possible conditions are considered
+llvm::Value*
+ControlIR::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar) {
+ EXPAND_CONTEXT UNUSED(function);
+ AST* root = context.pass->man->root;
+ llvm::IRBuilder<>& builder = llvm->irBuilder;
+ assert(exprSwitch.operands.size() >= 2);
+ assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
+
+ int countCases = exprSwitch.operands.size() - 1;
+ llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
+ builder.SetInsertPoint(blockEpilog);
+ llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(exprSwitch));
+ llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
+ llvm::Type* typI8 = llvm::Type::getInt8Ty(llvm->llvmContext);
+
+ builder.SetInsertPoint(blockProlog);
+ llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
+ llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm->llvmContext, "caseDefault", function->raw);
+ llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(
+ typeinference::doAutomaticTypeConversion(conditionSwitch, typI8, builder),
+ blockDefault,
+ countCases);
+
+ for (int size = exprSwitch.operands.size(), i = 2; i < size; ++i) {
+ llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(i), function->raw);
+
+ llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
+ builder.SetInsertPoint(blockCase);
+ llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
+ builder.CreateBr(blockEpilog);
+
+ ret->addIncoming(resultCase, builder.GetInsertBlock());
+ builder.SetInsertPoint(blockProlog);
+ instructionSwitch->addCase(
+ dyn_cast<llvm::ConstantInt>(
+ typeinference::doAutomaticTypeConversion(condCase, typI8, builder)),
+ blockCase);
+ }
+
+ //compile default block:
+ builder.SetInsertPoint(blockDefault);
+ CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
+ llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
+ builder.CreateBr(blockEpilog);
+ ret->addIncoming(resultDefault, builder.GetInsertBlock());
+ builder.SetInsertPoint(blockEpilog);
+
+ return ret;
+}
+
+llvm::Value*
+ControlIR::compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar) {
+ EXPAND_CONTEXT UNUSED(function);
+ AST* root = context.pass->man->root;
+ llvm::IRBuilder<>& builder = llvm->irBuilder;
+ llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
+ const ExpandedType& typVariant = root->getType(exprSwitch.operands.at(0));
+ llvm::Type* typVariantRaw = llvm->toLLVMType(typVariant);
+
+ assert(typVariant->__operands.size() == exprSwitch.operands.size() - 1 && "Ill-formed Switch Variant");
+
+ int casesCount = exprSwitch.operands.size();
+ llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
+ builder.SetInsertPoint(blockEpilog);
+ llvm::Type* resultType = llvm->toLLVMType(root->getType(exprSwitch));
+ llvm::PHINode *ret = builder.CreatePHI(resultType, casesCount, NAME("switch"));
+
+ builder.SetInsertPoint(blockProlog);
+ llvm::Value * conditionSwitchRaw = scope->process(exprSwitch.operands.at(0));
+ llvm::Value* idRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({0}));
+
+ //Dereference preparation
+ const bool flagPrepareDerefence = std::any_of(typVariant->__operands.begin(), typVariant->__operands.end(), [](const TypeAnnotation& op){
+ return op.isValid();
+ });
+
+ llvm::Value* addrAsStorage = nullptr;
+ if (flagPrepareDerefence){
+ assert(exprSwitch.bindings.size() && "Switch condition alias not found");
+ llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
+ llvm::Value* storageRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({1}));
+ addrAsStorage = llvm->irBuilder.CreateAlloca(typStorageRaw);
+ llvm->irBuilder.CreateStore(storageRaw, addrAsStorage);
+ }
+
+ llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(idRaw, nullptr, casesCount);
+ llvm::BasicBlock* blockDefaultUndefined;
+ std::list<CodeScope*>::const_iterator scopeCaseIt = exprSwitch.blocks.begin();
+ for (int instancesSize = exprSwitch.operands.size()-1, instId = 0; instId < instancesSize; ++instId) {
+ llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(instId), function->raw);
+ builder.SetInsertPoint(blockCase);
+ IBruteScope* unitCase = function->getScopeUnit(*scopeCaseIt);
+ const ExpandedType& instType = ExpandedType(typVariant->__operands.at(instId));
+
+ //Actual variant derefence
+ if (instType->isValid()) {
+ string identCondition = exprSwitch.bindings.front();
+ llvm::Type* instTypeRaw = llvm->toLLVMType(instType);
+ llvm::Value* addrAsInst = llvm->irBuilder.CreateBitOrPointerCast(addrAsStorage, instTypeRaw->getPointerTo());
+ llvm::Value* instRaw = llvm->irBuilder.CreateLoad(instTypeRaw, addrAsInst);
+ const Symbol& identSymb = unitCase->bindArg(instRaw, move(identCondition));
+ Attachments::put<TypeInferred>(identSymb, instType);
+ }
+
+ llvm::Value* resultCase = function->getScopeUnit(*scopeCaseIt)->compile();
+ builder.CreateBr(blockEpilog);
+
+ ret->addIncoming(resultCase, blockDefaultUndefined = builder.GetInsertBlock());
+ builder.SetInsertPoint(blockProlog);
+ instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, exprSwitch.operands.at(instId+1).getValueDouble())), blockCase);
+ ++scopeCaseIt;
+ }
+
+ instructionSwitch->setDefaultDest(blockDefaultUndefined);
+ builder.SetInsertPoint(blockEpilog);
+ return ret;
+}
+
+llvm::Value*
+ControlIR::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar) {
+ EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
+
+ Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm->llvmContext));
+ //ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
+
+ /*
+ std::vector<Constant *> chars;
+ chars.reserve(size+1);
+
+ for (size_t i=0; i< size; ++i){
+ chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
+ }
+ chars[size] = ConstantInt::get(typI8, 0);
+ */
+
+ Value* rawData = ConstantDataArray::getString(llvm->llvmContext, data);
+ Value* rawPtrData = llvm->irBuilder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 1, false));
+ llvm->irBuilder.CreateStore(rawData, rawPtrData);
+ return llvm->irBuilder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
+}
+
+llvm::Value*
+ControlIR::compileSequence(const Expression &expr){
+ EXPAND_CONTEXT UNUSED(scope); UNUSED(llvm);
+
+ llvm::Value* result;
+ for(CodeScope* scope: expr.blocks){
+ result = function->getScopeUnit(scope)->compile();
+ }
+
+ return result;
+}
+
+
diff --git a/cpp/src/compilation/advancedinstructions.h b/cpp/src/compilation/control.h
similarity index 76%
rename from cpp/src/compilation/advancedinstructions.h
rename to cpp/src/compilation/control.h
index 4826c2f..556bc09 100644
--- a/cpp/src/compilation/advancedinstructions.h
+++ b/cpp/src/compilation/control.h
@@ -1,79 +1,73 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * File: AdvancedInstructions.h
+ * File: ControlIR.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:00 PM
*/
/**
* \file advancedinstructions.h
* \brief Compound statements compilation
*/
#ifndef INSTRUCTIONSADVANCED_H
#define INSTRUCTIONSADVANCED_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include <vector>
namespace xreate {
namespace compilation {
/** \brief Advanced compilation primitives */
-class AdvancedInstructions {
+class ControlIR {
public:
- AdvancedInstructions(compilation::Context ctx);
-
- /** \brief Array subscript access operator compilation*/
- llvm::Value* compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string ident = "");
+ ControlIR(compilation::Context ctx);
/** \brief Struct field access operator compilation*/
- llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
+ llvm::Value* compileStructIndex(llvm::Value* aggregate, ExpandedType aggrT, const std::list<std::string>& indices);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
/** \brief `loop map` statement compilation*/
llvm::Value* compileMapSolidOutput(const Expression &expr, const std::string hintRetVar = "");
/** \brief `loop fold` statement compilation*/
- llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
+ llvm::Value* compileFold(const Expression& loopE, const std::string& hintAlias="");
/** \brief `loop` statement compilation*/
llvm::Value* compileFoldInf(const Expression& fold, const std::string& ident="");
/** \brief `if` statement compilation*/
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
/** \brief `switch` statement compilation*/
llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
/** \brief `switch` statement compilation*/
llvm::Value* compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar);
/** \brief `switch variant` statement compilation*/
llvm::Value* compileConstantStringAsPChar(const std::string &data, const std::string& hintRetVar);
- /** \brief Contiguous memory list implementation*/
- llvm::Value* compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar);
-
/** \brief `seq` statement compilation */
llvm::Value* compileSequence(const Expression &expr);
private:
compilation::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif /* INSTRUCTIONSADVANCED_H */
diff --git a/cpp/src/compilation/scopedecorators.h b/cpp/src/compilation/decorators.h
similarity index 54%
rename from cpp/src/compilation/scopedecorators.h
rename to cpp/src/compilation/decorators.h
index b84b9ae..87d4934 100644
--- a/cpp/src/compilation/scopedecorators.h
+++ b/cpp/src/compilation/decorators.h
@@ -1,188 +1,237 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: scopedecorators.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on February 24, 2017, 11:35 AM
*/
/**
* \file scopedecorators.h
- * \brief Basic code block compilation xreate::compilation::ICodeScopeUnit decorators
+ * \brief Basic code block compilation xreate::compilation::IBruteScope decorators
*/
#ifndef SCOPEDECORATORS_H
#define SCOPEDECORATORS_H
#include "ast.h"
-#include "compilation/targetinterpretation.h"
-#include "compilation/versions.h"
#include "compilation/transformations.h"
-#include "compilation/polymorph.h"
-#include "compilation/latex.h"
#include "analysis/typeinference.h"
+#include "compilation/demand.h"
+#include "compilation/polymorph.h"
+#include "compilation/targetinterpretation.h"
+
+#ifndef XREATE_CONFIG_MIN
+ #include "compilation/versions.h"
+ #include "compilation/polymorph.h"
+#endif
+
#include <list>
-namespace xreate {
-
+namespace xreate {
+
class CompilePass;
namespace compilation {
-class ICodeScopeUnit;
-class IFunctionUnit;
+class IBruteScope;
+class IBruteFunction;
/**\brief Provides caching ability for code scope compilation
- * \extends xreate::compilation::ICodeScopeUnit
+ * \extends xreate::compilation::IBruteScope
*/
template<class Parent>
class CachedScopeDecorator: public Parent{
typedef CachedScopeDecorator<Parent> SELF;
public:
- CachedScopeDecorator(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+ CachedScopeDecorator(const CodeScope* const codeScope, IBruteFunction* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
Symbol bindArg(llvm::Value* value, std::string&& alias)
{
//ensure existence of an alias
assert(Parent::scope->__identifiers.count(alias));
//memorize new value for an alias
ScopedSymbol id{Parent::scope->__identifiers.at(alias), versions::VERSION_NONE};
__rawVars[id] = value;
-
+
return Symbol{id, Parent::scope};
}
void bindArg(llvm::Value* value, const ScopedSymbol& s) {
__rawVars[s] = value;
}
-
- llvm::Value* compile(const std::string& hintBlockDecl="") override{
+
+ llvm::Value* compile(const std::string& aliasBlock="") override{
if (__rawVars.count(ScopedSymbol::RetSymbol)){
return __rawVars[ScopedSymbol::RetSymbol];
}
-
- return Parent::compile(hintBlockDecl);
+
+ return Parent::compile(aliasBlock);
}
- llvm::Value*
+ llvm::Value*
processSymbol(const Symbol& s, std::string hintRetVar) override{
const CodeScope* scope = s.scope;
SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(scope));
if (self->__rawVars.count(s.identifier)){
return self->__rawVars[s.identifier];
}
//Declaration could be overriden
/*
Expression declaration = CodeScope::getDefinition(s, true);
if (!declaration.isDefined()){
assert(__declarationsOverriden.count(s.identifier));
declaration = __declarationsOverriden[s.identifier];
} else {
(false); //in case of binding there should be raws provided.
}
}
*/
llvm::Value* resultRaw = Parent::processSymbol(s, hintRetVar);
self->__rawVars.emplace(s.identifier, resultRaw);
return resultRaw;
}
- void
+ void
overrideDeclarations(std::list<std::pair<Symbol, Expression>> bindings){
reset();
-
+
for (auto entry: bindings){
SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(entry.first.scope));
assert(self == this);
-
+
self->__declarationsOverriden.emplace(entry.first.identifier, entry.second);
}
}
- void registerChildScope(std::shared_ptr<ICodeScopeUnit> scope){
+ void registerChildScope(std::shared_ptr<IBruteScope> scope){
__childScopes.push_back(scope);
}
void reset(){
__rawVars.clear();
__declarationsOverriden.clear();
__childScopes.clear();
}
private:
std::unordered_map<ScopedSymbol, Expression> __declarationsOverriden;
std::unordered_map<ScopedSymbol,llvm::Value*> __rawVars;
- std::list<std::shared_ptr<ICodeScopeUnit>> __childScopes;
+ std::list<std::shared_ptr<IBruteScope>> __childScopes;
};
/** \brief Provides automatic type conversion
- * \extends xreate::compilation::ICodeScopeUnit
+ * \extends xreate::compilation::IBruteScope
*/
template<class Parent>
class TypeConversionScopeDecorator: public Parent {
public:
- TypeConversionScopeDecorator(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
-
- llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="") override {
- llvm::Value* resultR = Parent::process(expr, hintVarDecl);
-
+ TypeConversionScopeDecorator(const CodeScope* const codeScope, IBruteFunction* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+
+ llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="", const TypeAnnotation& expectedT = TypeAnnotation()) override {
+ llvm::Value* resultR = Parent::process(expr, hintVarDecl, expectedT);
+
if(!expr.type.isValid()) {
- return resultR;
+ return resultR;
}
ExpandedType exprT = Parent::pass->man->root->getType(expr);
llvm::Type* exprTR = Parent::pass->man->llvm->toLLVMType(exprT);
- return typeinference::doAutomaticTypeConversion(resultR, exprTR, Parent::pass->man->llvm->builder);
+ return typeinference::doAutomaticTypeConversion(resultR, exprTR, Parent::pass->man->llvm->irBuilder);
}
};
+#ifndef XREATE_CONFIG_MIN
/**\brief The default code scope compilation implementation
- * \extends xreate::compilation::ICodeScopeUnit
+ * \extends xreate::compilation::IBruteScope
*/
-typedef CachedScopeDecorator<
- TypeConversionScopeDecorator<
- latex::LatexBruteScopeDecorator<
- polymorph::PolymorphCodeScopeUnit<
- compilation::TransformationsScopeDecorator<
- interpretation::InterpretationScopeDecorator<
- versions::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>>>>>
-
- DefaultCodeScopeUnit;
-
-} //end of compilation namespace
-
-struct CachedScopeDecoratorTag;
-struct VersionsScopeDecoratorTag;
-
-template<>
-struct DecoratorsDict<CachedScopeDecoratorTag>{
- typedef compilation::CachedScopeDecorator<
- compilation::TypeConversionScopeDecorator<
- latex::LatexBruteScopeDecorator<
- polymorph::PolymorphCodeScopeUnit<
- compilation::TransformationsScopeDecorator<
+typedef
+ CachedScopeDecorator<
+ TypeConversionScopeDecorator<
+ latex::LatexBruteScopeDecorator<
+ polymorph::PolymorphBruteScopeDecorator<
+ compilation::TransformationsScopeDecorator<
interpretation::InterpretationScopeDecorator<
- versions::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>>>>>
-
- result;
-};
-
-template<>
-struct DecoratorsDict<VersionsScopeDecoratorTag>{
- typedef versions::VersionsScopeDecorator<
- compilation::BasicCodeScopeUnit> result;
-};
-
+ versions::VersionsScopeDecorator<
+ compilation::BasicBruteScope
+ >>>>>>>
+ DefaultCodeScopeUnit;
+
+ } //end of compilation namespace
+
+ struct CachedScopeDecoratorTag;
+ struct VersionsScopeDecoratorTag;
+
+ template<>
+ struct DecoratorsDict<CachedScopeDecoratorTag>{
+ typedef compilation::CachedScopeDecorator<
+ compilation::TypeConversionScopeDecorator<
+ latex::LatexBruteScopeDecorator<
+ polymorph::PolymorphBruteScopeDecorator<
+ compilation::TransformationsScopeDecorator<
+ interpretation::InterpretationScopeDecorator<
+ versions::VersionsScopeDecorator<
+ compilation::BasicBruteScope
+ >>>>>>>
+
+ result;
+ };
+
+ template<>
+ struct DecoratorsDict<VersionsScopeDecoratorTag>{
+ typedef
+ versions::VersionsScopeDecorator<
+ compilation::BasicBruteScope
+ >
+ result;
+ };
+
+#else
+ /**\brief The default code scope compilation implementation
+ * \extends xreate::compilation::IBruteScope
+ */
+ typedef
+ CachedScopeDecorator<
+ TypeConversionScopeDecorator<
+ interpretation::InterpretationScopeDecorator<
+ demand::DemandBruteScopeDecorator<
+ polymorph::PolymorphBruteScopeDecorator<
+ compilation::BasicBruteScope
+ >>>>>
+ DefaultCodeScopeUnit;
+
+ } //end of compilation namespacef
+
+ struct CachedScopeDecoratorTag;
+
+ template<>
+ struct DecoratorsDict<CachedScopeDecoratorTag>{
+ typedef compilation::CachedScopeDecorator<
+ compilation::TypeConversionScopeDecorator<
+ interpretation::InterpretationScopeDecorator<
+ demand::DemandBruteScopeDecorator<
+ polymorph::PolymorphBruteScopeDecorator<
+ compilation::BasicBruteScope
+ >>>>>
+ result;
+ };
+
+ typedef
+ demand::DemandBruteFnDecorator<
+ //polymorph::PolymorphBruteFnDecorator<
+ compilation::BasicBruteFunction
+ > BruteFunctionDefault;
+#endif
} //end of xreate
#endif /* SCOPEDECORATORS_H */
diff --git a/cpp/src/compilation/demand.cpp b/cpp/src/compilation/demand.cpp
new file mode 100644
index 0000000..4edba65
--- /dev/null
+++ b/cpp/src/compilation/demand.cpp
@@ -0,0 +1,22 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on June 23, 2018, 4:33 PM
+ */
+
+/**
+ * \file src/compilation/latex.h
+ * \brief Latex(Late Context) support
+ */
+
+#include "compilation/demand.h"
+#include "llvmlayer.h"
+
+namespace xreate{
+namespace demand{
+
+}
+}
\ No newline at end of file
diff --git a/cpp/src/compilation/demand.h b/cpp/src/compilation/demand.h
new file mode 100644
index 0000000..9a9e64b
--- /dev/null
+++ b/cpp/src/compilation/demand.h
@@ -0,0 +1,101 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on June 23, 2018, 2:51 PM
+ *
+ */
+
+#ifndef LATEX_H
+#define LATEX_H
+
+#include "query/demand.h"
+#include "analysis/utils.h"
+#include "pass/compilepass.h"
+
+namespace xreate{namespace demand{
+
+template<class Parent>
+class DemandBruteFnDecorator : public Parent{
+public:
+ DemandBruteFnDecorator(ManagedFnPtr f, CompilePass *p): Parent(f, p){}
+
+protected:
+ std::vector<llvm::Type *>
+ prepareSignature() override{
+ std::vector<llvm::Type *> &&signature = Parent::prepareSignature();
+
+ DemandQuery* query = reinterpret_cast<DemandQuery *> (Parent::pass->man->transcend->getQuery(QueryId::DemandQuery));
+ const Demand& demand = query->getFnDemand(Parent::function->getName());
+ signature.reserve(signature.size() + demand.size());
+
+ unsigned int argOffset = signature.size();
+ for(const auto &rec: demand){
+ TypeAnnotation argTCust(TypeOperator::ALIAS, {});
+ argTCust.__valueCustom = rec.second;
+ const ExpandedType &argT = Parent::pass->man->root->expandType(argTCust);
+ Expression bindingE;
+ bindingE.type = argT;
+ llvm::Type *argTRaw = Parent::pass->man->llvm->toLLVMType(argT);
+
+ Parent::function->addBinding(
+ Atom<Identifier_t>(std::string(rec.first)),
+ std::move(bindingE),
+ argOffset++
+ );
+ signature.push_back(argTRaw);
+ }
+
+ return signature;
+ }
+};
+
+/**
+ * \brief Latex aware \ref xreate::compilation::IBruteScope decorator
+ * \implements xreate::compilation::IBruteScope
+ */
+template<class Parent>
+class DemandBruteScopeDecorator : public Parent{
+public:
+ DemandBruteScopeDecorator(const CodeScope *const codeScope, compilation::IBruteFunction *f, CompilePass *compilePass)
+ : Parent(codeScope, f, compilePass){}
+
+ compilation::IFnInvocation *
+ findFunction(const Expression& opCall){
+ DemandQuery* query = reinterpret_cast<DemandQuery *> (Parent::pass->man->transcend->getQuery(QueryId::DemandQuery));
+ const std::string &calleeName = opCall.getValueString();
+ compilation::IFnInvocation *opInvocBase = Parent::findFunction(opCall);
+
+ const Demand &demand = query->getFnDemand(calleeName);
+ if(!demand.size()) return opInvocBase;
+
+ //prepare additional arguments
+ std::vector<llvm::Value*> argsDemand;
+ argsDemand.reserve(demand.size());
+
+ const Supply& argsActual = query->getFnSupply(ASTSite{opCall.id});
+ for(const auto& arg: demand){
+ TypeAnnotation argTCust(TypeOperator::ALIAS, {});
+ argTCust.__valueCustom = arg.second;
+ const ExpandedType &argScheme = Parent::pass->man->root->expandType(argTCust);
+ //llvm::Type* argSchemeRaw = Parent::pass->man->llvm->toLLVMType(argScheme);
+ const Gringo::Symbol argTrAtom = argsActual.at(arg.first);
+ Expression argE = analysis::representTransExpression(argTrAtom, argScheme, Parent::pass->man->transcend);
+ argE.type = argScheme;
+ llvm::Value* argValueRaw = Parent::process(argE);
+
+ argsDemand.push_back(argValueRaw);
+ }
+
+ return new compilation::HiddenArgsFnInvocation(std::move(argsDemand), opInvocBase);
+ }
+};
+
+}} //end of namespace xreate::demand
+
+#endif /* LATEX_H */
+
diff --git a/cpp/src/compilation/interpretation-instructions.cpp b/cpp/src/compilation/i12ninst.cpp
similarity index 97%
rename from cpp/src/compilation/interpretation-instructions.cpp
rename to cpp/src/compilation/i12ninst.cpp
index f4387bd..72d320d 100644
--- a/cpp/src/compilation/interpretation-instructions.cpp
+++ b/cpp/src/compilation/i12ninst.cpp
@@ -1,113 +1,113 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 15, 2018, 5:32 PM
*/
-#include "compilation/interpretation-instructions.h"
+#include "compilation/i12ninst.h"
#include "analysis/interpretation.h"
#include "transcendlayer.h"
#include "targets.h"
#include "aux/latereasoning.h"
#include "latetranscend.h"
#include "aux/transcend-decorators.h"
#include "compilation/targetinterpretation.h"
using namespace std;
using namespace xreate::latereasoning;
namespace xreate{
namespace interpretation{
Expression
IntrinsicQueryInstruction::process(const Expression& expression) {
AST* ast = static_cast<TargetInterpretation*> (__fnI12n->man)->ast;
TranscendLayer* transcend = static_cast<TargetInterpretation*> (__fnI12n->man)->pass->man->transcend;
ExpandedType targetT = ast->getType(expression);
assert(expression.operands.size() == 1);
assert(expression.operands.front().__state == Expression::STRING);
assert(targetT->__operator == TypeOperator::LIST_ARRAY);
std::string namePredicate = expression.operands.front().getValueString();
StaticModel model = (static_cast<TargetInterpretation*> (__fnI12n->man))->pass->man->transcend->query(namePredicate);
Expression result(Operator::LIST,{});
result.operands.reserve(model.size());
ExpandedType elementT = targetT->__operands.at(0).__operator == TypeOperator::SLAVE
? dereferenceSlaveType(ExpandedType(targetT->__operands.at(0)), transcend)
: ExpandedType(targetT->__operands.at(0));
if(model.size()) {
if (elementT->__operator == TypeOperator::LIST_RECORD) {
//edge case, content's type is LIST_NAMED:
for(const auto& row : model) {
result.operands.push_back(representTransExpression(row.second, elementT, transcend));
}
} else {
for (const auto& row : model) {
assert(row.second.args().size);
result.operands.push_back(representTransExpression(row.second.args()[0], elementT, transcend));
}
}
}
return result;
}
llvm::Value*
IntrinsicQueryInstruction::processLate(const Expression& expression, const compilation::Context& context) {
assert(expression.blocks.size());
CodeScope* body = expression.blocks.front();
PassManager* man = static_cast<TargetInterpretation*> (__fnI12n->man)->pass->man;
compilation::ICodeScopeUnit* bodyBrute = context.function->getScopeUnit(body);
llvm::Type* instructionT = man->llvm->toLLVMType(man->root->getType(expression));
Expression atomNameE = __fnI12n->getScope(context.scope->scope)->process(expression.operands.front());
assert(atomNameE.__state == Expression::STRING);
string atomName = atomNameE.getValueString();
std::string argName = expression.bindings.front();
ExpandedType argT = man->root->getType(body->getDefinition(body->getSymbol(argName)));
if (argT->__operator == TypeOperator::SLAVE){
argT = dereferenceSlaveType(argT, man->transcend);
}
auto transcend =
Decorators<LateReasoningTranscendDecoratorTag>::getInterface(man->transcend);
LateReasoningCompiler* compiler =
new latereasoning::LateReasoningCompiler(__fnI12n, context);
- SymbolPacked targetSP = transcend->pack(Attachments::get<SymbolAlias>(expression));
+ SymbolPacked targetSP = transcend->pack(Attachments::get<ExprAlias_A>(expression));
LateAnnotationsGroup feedbackAG = transcend->queryLate(atomName);
for(const auto& feedback : feedbackAG.annotations) {
SymbolPacked targetExpectedSP = ParseImplAtom<SymbolPacked>::get(feedback.first);
if (targetExpectedSP == targetSP) {
const LateAnnotation& annotation = feedback.second;
return compiler->compileAutoExpand(annotation, instructionT, "",
[transcend, &argT, this, body, bodyBrute, &argName](const Gringo::Symbol & atomRaw) {
InterpretationScope* bodyI12n = __fnI12n->getScope(body);
Expression argValue;
if (argT->__operator == TypeOperator::LIST_RECORD) {
argValue = representTransExpression(atomRaw, argT, transcend);
} else {
argValue = representTransExpression(atomRaw.args()[0], argT, transcend);
}
bodyI12n->overrideBindings({
{argValue, argName}});
bodyBrute->reset();
return bodyBrute->compile();
});
}
}
assert(false && "No appropriate late annotation");
return nullptr; //should not be ever reachable
}
}
} //end of xreate::interpretation
diff --git a/cpp/src/compilation/interpretation-instructions.h b/cpp/src/compilation/i12ninst.h
similarity index 100%
rename from cpp/src/compilation/interpretation-instructions.h
rename to cpp/src/compilation/i12ninst.h
diff --git a/cpp/src/compilation/intrinsics.cpp b/cpp/src/compilation/intrinsics.cpp
new file mode 100644
index 0000000..c8582ba
--- /dev/null
+++ b/cpp/src/compilation/intrinsics.cpp
@@ -0,0 +1,58 @@
+//March 2020
+
+#include "compilation/intrinsics.h"
+#include "analysis/utils.h"
+#include "llvmlayer.h"
+
+using namespace std;
+
+namespace xreate{ namespace compilation{
+
+llvm::Value*
+IntrinsicCompiler::compile(const Expression& e, const Context& context, const std::string& hintAlias){
+ switch ((IntrinsicFn) e.getValueDouble()){
+ case IntrinsicFn::ARR_INIT:{
+ return nullptr;
+// const ExpandedType& typAggr = context.pass->man->root->getType(e);
+// llvm::Type* typAggrRaw = context.pass->man->llvm->toLLVMType(typAggr);
+// llvm::Value* lengthRaw = context.scope->process(e.operands.at(0));
+//
+// ContainerInst engine(context);
+// return engine.array_init(lengthRaw, typAggrRaw);
+ }
+
+ default: break;
+ }
+
+ assert(false);
+ return nullptr;
+}
+
+Expression
+IntrinsicCompiler::interpret(const Expression& e){
+ switch ((IntrinsicFn) e.getValueDouble()){
+ case IntrinsicFn::REC_FIELDS: {
+ return rec_fields(e);
+ }
+ default: break;
+ }
+
+ assert(false);
+ return Expression();
+}
+
+Expression
+IntrinsicCompiler::rec_fields(const Expression& e){
+ TypesHelper helper(__man->llvm);
+ assert(e.operands.size() == 1);
+
+ const Expression argTypeE = e.operands.at(0);
+ assert(argTypeE.__state == Expression::STRING);
+ const string& argTypeS = argTypeE.getValueString();
+ const ExpandedType argTypeT = __man->root->findType(argTypeS);
+
+ const auto& fields = helper.getRecordFields(argTypeT);
+ return analysis::representVecStr(fields);
+}
+
+}}
\ No newline at end of file
diff --git a/cpp/src/compilation/intrinsics.h b/cpp/src/compilation/intrinsics.h
new file mode 100644
index 0000000..98f3c42
--- /dev/null
+++ b/cpp/src/compilation/intrinsics.h
@@ -0,0 +1,26 @@
+//March 2020
+
+#ifndef XREATE_INTRINSICS_H
+#define XREATE_INTRINSICS_H
+
+#include "ast.h"
+#include "pass/compilepass.h"
+namespace llvm {
+ class Value;
+}
+
+namespace xreate{ namespace compilation{
+class IntrinsicCompiler{
+public:
+ IntrinsicCompiler(PassManager* manager): __man(manager){};
+
+ llvm::Value* compile(const Expression& e, const Context& context, const std::string& hintAlias);
+ Expression interpret(const Expression& e);
+
+private:
+ PassManager* __man;
+
+ Expression rec_fields(const Expression& e);
+};
+}}
+#endif //XREATE_INTRINSICS_H
diff --git a/cpp/src/compilation/latetranscend.cpp b/cpp/src/compilation/latetranscend.cpp
index 54ce3e7..0c584ed 100644
--- a/cpp/src/compilation/latetranscend.cpp
+++ b/cpp/src/compilation/latetranscend.cpp
@@ -1,183 +1,183 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on May 26, 2018, 3:54 PM
*/
/**
* \class xreate::latereasoning::LateReasoningCompiler
* Provides Late Transcend feature. See [Late Transcend](/d/transcend/late-transcend/) for the general overview.
*/
#include "compilation/latetranscend.h"
//#include "aux/latereasoning.h"
-#include "compilation/scopedecorators.h"
+#include "compilation/decorators.h"
#include "analysis/interpretation.h"
#include "compilation/targetinterpretation.h"
#include <vector>
using namespace xreate::interpretation;
using namespace xreate::compilation;
using namespace std;
namespace xreate{
namespace latereasoning{
#define HINT(x) (hint.empty()? x : hint)
std::map<SymbolPacked, Expression> LateReasoningCompiler:: __dictGuardDefinitions = std::map<SymbolPacked, Expression>();
llvm::Value*
LateReasoningCompiler::processSwitchLateStatement(const Expression& expr, const std::string& hint) {
AST* root = __context.pass->man->root;
LLVMLayer* llvm = __context.pass->man->llvm;
CodeScope* scopeBody = expr.blocks.front();
Symbol guardS = Symbol{scopeBody->getSymbol(expr.bindings.front()), scopeBody};
const ExpandedType& guardT = root->getType(expr.operands.at(0));
const ExpandedType& guardTPlain = guardT->__operator == TypeOperator::SLAVE?
interpretation::dereferenceSlaveType(guardT, __context.pass->man->transcend)
: guardT;
llvm::Value * guardRaw = __context.scope->process(expr.operands.at(0));
llvm::Type* instructionT = llvm->toLLVMType(root->getType(expr));
return compileExpand(guardS, guardRaw, guardTPlain, instructionT, hint, [this, scopeBody]() {
ICodeScopeUnit* bodyUnit = this->__context.function->getScopeUnit(scopeBody);
bodyUnit->reset();
return this->__context.function->getScopeUnit(scopeBody)->compile();
});
}
llvm::Value*
LateReasoningCompiler::compileAutoExpand(const LateAnnotation& annotation,
llvm::Type* resultT,
const std::string& hint,
Handler handler) {
TranscendLayer* transcend = __context.pass->man->transcend;
AST* root = __context.pass->man->root;
const std::list<SymbolPacked>& guardKeys = annotation.guardKeys;
std::list<Symbol> guardsToExpand;
for(const SymbolPacked key : guardKeys) {
if(!__dictGuardDefinitions.count(key)) {
const Symbol& keyS = transcend->unpack(key);
InterpretationScope* keyScope = __fnI12n->getScope(keyS.scope);
if (!keyScope->isBindingDefined(keyS.identifier)) {
guardsToExpand.push_back(keyS);
}
}
}
typedef std::function < llvm::Value * () > Compiler;
Compiler programInit([handler, annotation, this]() {
std::list<Expression>&& values = findKeys(annotation.guardKeys);
auto answer = annotation.select(values, __context.pass->man->root, __context.pass->man->transcend);
assert(answer);
return handler(*answer);
});
Compiler aggregate = std::accumulate(guardsToExpand.begin(), guardsToExpand.end(),
programInit,
[this, root, transcend, &resultT, hint](Compiler program, const Symbol & key) {
const ExpandedType& keyT = root->getType(CodeScope::getDefinition(key));
const ExpandedType& keyTPlain = keyT->__operator == TypeOperator::SLAVE?
interpretation::dereferenceSlaveType(keyT, transcend)
: keyT;
return Compiler([this, key, keyTPlain, resultT, hint, program](){
llvm::Value * keyRaw = __context.scope->processSymbol(key);
return compileExpand(key, keyRaw, keyTPlain, resultT, hint, program);
});
}
);
return aggregate();
}
llvm::Value*
LateReasoningCompiler::compileExpand(const Symbol& keyS,
llvm::Value* keyRaw,
const ExpandedType& domainT,
llvm::Type* resultT,
const std::string& hint,
CompilerHandler compilerBody) {
assert(domainT->__operator == TypeOperator::VARIANT);
std::list<Expression> domInstancesList = generateAllInstancesInDomain2(domainT);
std::vector<Expression> domInstances(domInstancesList.begin(), domInstancesList.end());
const int countInstances = domInstances.size();
assert(countInstances);
TranscendLayer* transcend = __context.pass->man->transcend;
SymbolPacked keyP = transcend->pack(keyS);
LLVMLayer* llvm = __context.pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
compilation::IFunctionUnit* function = __context.function;
llvm::Type* typI8 = llvm::Type::getInt8Ty(llvm->llvmContext);
llvm::Value* keyVariantRaw = builder.CreateExtractValue(keyRaw, llvm::ArrayRef<unsigned>({0}));
llvm::SwitchInst* instructionSwitch = builder.CreateSwitch(keyVariantRaw, nullptr, countInstances);
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(
llvm->llvmContext, "epilog", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::PHINode *ret = builder.CreatePHI(resultT, countInstances, HINT("reverse"));
llvm::BasicBlock* blockDefault = nullptr;
for (int instanceId = 0; instanceId < countInstances; ++instanceId) {
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(
llvm->llvmContext,
"case" + std::to_string(instanceId),
function->raw);
if(instanceId == 0) blockDefault = blockCase;
builder.SetInsertPoint(blockCase);
//assign guard values
const Expression& instanceE = domInstances.at(instanceId);
__dictGuardDefinitions[keyP] = instanceE;
// __fnI12n->getScope(keyS.scope)->overrideBindings({
// {instanceE, keyS.identifier}
// });
//invoke further compilation handler
llvm::Value* resultCase = compilerBody();
ret->addIncoming(resultCase, builder.GetInsertBlock());
instructionSwitch->addCase(llvm::dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, instanceId)), blockCase);
builder.CreateBr(blockEpilog);
}
//erase guard assignment
__dictGuardDefinitions.erase(keyP);
instructionSwitch->setDefaultDest(blockDefault);
builder.SetInsertPoint(blockEpilog);
return ret;
}
std::list<Expression>
LateReasoningCompiler::findKeys(const std::list<SymbolPacked>& keys) {
TranscendLayer* transcend = __context.pass->man->transcend;
std::list<Expression> result;
InterpretationScope* scopeI12n = __fnI12n->getScope(__context.scope->scope);
std::transform(keys.begin(), keys.end(), std::inserter(result, result.end()),
[this, scopeI12n, transcend](const SymbolPacked & key) {
if (__dictGuardDefinitions.count(key)){
return __dictGuardDefinitions.at(key);
}
return scopeI12n->processSymbol(transcend->unpack(key));
});
return result;
}
}
}
diff --git a/cpp/src/compilation/latex.cpp b/cpp/src/compilation/latex.cpp
deleted file mode 100644
index 9a4d11e..0000000
--- a/cpp/src/compilation/latex.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Author: pgess <v.melnychenko@xreate.org>
- * Created on June 23, 2018, 4:33 PM
- */
-
-/**
- * \file src/compilation/latex.h
- * \brief Latex(Late Context) support
- */
-
-#include "compilation/latex.h"
-#include "analysis/interpretation.h"
-#include "llvmlayer.h"
-
-namespace xreate{
-namespace latex{
-
-ExpandedType
-getSubjectDomain(const std::string& subject, LatexQuery* query){
- std::list<Gringo::Symbol>&& column = query->getSubjectDomain(subject);
- return ExpandedType(interpretation::collapseColumn(column));
-}
-
-llvm::Value*
-ExtraArgsFnInvocation::operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
- args.insert(args.end(), __argsLatex.begin(), __argsLatex.end());
-
- return __parent->operator ()(std::move(args), hintDecl);
-}
-
-}
-}
\ No newline at end of file
diff --git a/cpp/src/compilation/latex.h b/cpp/src/compilation/latex.h
deleted file mode 100644
index cbb7529..0000000
--- a/cpp/src/compilation/latex.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-/*
- * Author: pgess <v.melnychenko@xreate.org>
- * Created on June 23, 2018, 2:51 PM
- *
- * \file latex.h
- * \brief latex
- */
-
-#ifndef LATEX_H
-#define LATEX_H
-
-#include "compilation/latetranscend.h"
-#include "compilation/interpretation-instructions.h"
-#include "query/latex.h"
-#include "pass/compilepass.h"
-#include "analysis/interpretation.h"
-#include "compilation/targetinterpretation.h"
-
-namespace xreate{
-namespace latex{
-
-ExpandedType
-getSubjectDomain(const std::string &subject, LatexQuery *query);
-
-/** \brief Latex(Late Context)-aware decorator for \ref xreate::compilation::IFunctionUnit
- * \extends xreate::compilation::IFunctionUnit
- */
-template<class Parent>
-class LatexBruteFunctionDecorator : public Parent{
-public:
-
- LatexBruteFunctionDecorator(ManagedFnPtr f, CompilePass *p)
- : Parent(f, p){
- __query = reinterpret_cast<LatexQuery *> (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery));
- }
-
-protected:
- std::vector<llvm::Type *>
- prepareSignature(){
- std::vector<llvm::Type *> &&signature = Parent::prepareSignature();
-
- const Demand &demand = __query->getFnDemand(Parent::function->getName());
- signature.reserve(signature.size() + demand.size());
-
- int subjectId = __query->LatexParametersOffset;
- for(const std::string &subject: demand){
- const ExpandedType &subjectT = getSubjectDomain(subject, __query);
- Expression bindingE;
- bindingE.type = subjectT;
- std::string argCaption = std::string("latex_") + subject;
- Parent::function->addBinding(
- Atom<Identifier_t>(std::string(argCaption)),
- std::move(bindingE),
- subjectId++);
-
- llvm::Type *subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT);
- signature.push_back(subjectTRaw);
- }
-
- return signature;
- }
-
-public:
- LatexQuery *__query;
-};
-
-/** \brief %Function invocation operator decorator to handle latex enabled functions with hidden extra arguments */
-class ExtraArgsFnInvocation : public compilation::IFnInvocation{
-public:
-
- ExtraArgsFnInvocation(std::vector<llvm::Value *> argsLatex, compilation::IFnInvocation *parent)
- : __argsLatex(argsLatex), __parent(parent){}
-
- llvm::Value *operator()(std::vector<llvm::Value *> &&args, const std::string &hintDecl = "");
-
-private:
- std::vector<llvm::Value *> __argsLatex;
- compilation::IFnInvocation *__parent;
-};
-
-/**
- * \brief Latex aware \ref xreate::compilation::ICodeScopeUnit decorator
- * \implements xreate::compilation::ICodeScopeUnit
- */
-template<class Parent>
-class LatexBruteScopeDecorator : public Parent{
-public:
-
- LatexBruteScopeDecorator(const CodeScope *const codeScope, compilation::IFunctionUnit *f, CompilePass *compilePass)
- : Parent(codeScope, f, compilePass){}
-
- compilation::IFnInvocation *
- findFunction(const Expression &opCall){
- compilation::IFnInvocation *invocDefault = Parent::findFunction(opCall);
- const std::string &calleeName = opCall.getValueString();
- LatexQuery *query = reinterpret_cast<LatexQuery *> (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery));
-
- const Demand &fnCalleeDemand = query->getFnDemand(calleeName);
- if(!fnCalleeDemand.size()) return invocDefault;
-
- //prepare latex arguments
- std::vector<llvm::Value *> argsLatex;
- argsLatex.reserve(fnCalleeDemand.size());
-
- for(const std::string &subject: fnCalleeDemand){
- ExpandedType subjectT = getSubjectDomain(subject, query);
- llvm::Type *subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT);
- const latereasoning::LateAnnotation &decision = query->getDecision(subject, Parent::scope);
-
- compilation::Context ctx{this, Parent::function, Parent::pass};
- interpretation::InterpretationScope *scopeIntrpr =
- Parent::pass->targetInterpretation->transformContext(ctx);
- latereasoning::LateReasoningCompiler *compiler
- = new latereasoning::LateReasoningCompiler(
- dynamic_cast<interpretation::InterpretationFunction *>(scopeIntrpr->function), ctx);
-
- llvm::Value *subjectRaw = compiler->compileAutoExpand(
- decision,
- subjectTRaw,
- subject,
- [&](const Gringo::Symbol &decisionRaw){
- const Expression &decisionE = interpretation::representTransExpression(
- decisionRaw.args()[2], subjectT, Parent::pass->man->transcend);
- Attachments::put<TypeInferred>(decisionE, subjectT);
- return Parent::process(decisionE, subject);
- });
-
- argsLatex.push_back(subjectRaw);
- }
-
- return new ExtraArgsFnInvocation(std::move(argsLatex), invocDefault);
- }
-};
-
-}
-} //end of namespace xreate::context
-
-#endif /* LATEX_H */
-
diff --git a/cpp/src/compilation/operators.cpp b/cpp/src/compilation/operators.cpp
deleted file mode 100644
index 087b766..0000000
--- a/cpp/src/compilation/operators.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * operators.cpp
- *
- * Author: pgess <v.melnychenko@xreate.org>
- * Created on April 8, 2017, 1:35 PM
- */
-
-#include "operators.h"
-#include "llvmlayer.h"
-#include "ExternLayer.h"
-#include <vector>
-
-using namespace llvm;
-using namespace std;
-
-namespace xreate {
-
-namespace pointerarithmetic {
-
-llvm::Value*
-PointerArithmetic::add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl){
- LLVMLayer* llvm = context.pass->man->llvm;
-
- if (left->getType()->isPointerTy() && right->getType()->isIntegerTy()){
-
- std::vector<llvm::Value*> indexes{right};
- //{llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0)};
- //indexes.push_back(right);
-
- return llvm->builder.CreateGEP(left, llvm::ArrayRef<llvm::Value*>(indexes), hintVarDecl);
- }
-
- return nullptr;
-}
-}//end of pointgerarithmetic namespace
-
-llvm::Value*
-StructUpdate::add(const Expression& left, llvm::Value *leftRaw, const Expression& right, compilation::Context context, const std::string& hintVarDecl){\
- if (!(right.__state == Expression::COMPOUND && right.op == Operator::LIST)){
- return nullptr;
- }
-
- PassManager* man = context.pass->man;
-
- ExpandedType tyOperandLeft = man->root->getType(left);
-
- const std::vector<string> fieldsFormal = (tyOperandLeft.get().__operator == TypeOperator::CUSTOM)?
- man->llvm->layerExtern->getStructFields(man->llvm->layerExtern->lookupType(tyOperandLeft.get().__valueCustom))
- : tyOperandLeft.get().fields;
-
- std::map<std::string, size_t> indexFields;
- for(size_t i=0, size = fieldsFormal.size(); i<size; ++i){
- indexFields.emplace(fieldsFormal[i], i);
- }
-
- llvm::Value* result = leftRaw;
- for (size_t i=0; i<right.operands.size(); ++i){
- const Expression& value = right.operands.at(i);
- llvm::Value* valueRaw = context.scope->process(value, right.bindings.at(i));
- unsigned int fieldId = indexFields.at(right.bindings.at(i));
-
- result = man->llvm->builder.CreateInsertValue(result, valueRaw, llvm::ArrayRef<unsigned>({fieldId}));
- }
-
- return result;
-}
-
-} //end of xreate namespace
diff --git a/cpp/src/compilation/pointers.cpp b/cpp/src/compilation/pointers.cpp
new file mode 100644
index 0000000..5b70a05
--- /dev/null
+++ b/cpp/src/compilation/pointers.cpp
@@ -0,0 +1,44 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * operators.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on April 8, 2017, 1:35 PM
+ */
+
+#include "pointers.h"
+#include "llvmlayer.h"
+
+#ifdef XREATE_ENABLE_EXTERN
+ #include "ExternLayer.h"
+#endif
+
+#include <vector>
+
+using namespace llvm;
+using namespace std;
+
+namespace xreate {
+
+namespace pointers {
+
+llvm::Value*
+PointerArithmetic::add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl){
+ LLVMLayer* llvm = context.pass->man->llvm;
+
+ if (left->getType()->isPointerTy() && right->getType()->isIntegerTy()){
+
+ std::vector<llvm::Value*> indexes{right};
+ //{llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0)};
+ //indexes.push_back(right);
+
+ return llvm->irBuilder.CreateGEP(left, llvm::ArrayRef<llvm::Value*>(indexes), hintVarDecl);
+ }
+
+ return nullptr;
+}
+
+}//end of pointers namespace
+} //end of xreate namespace
diff --git a/cpp/src/compilation/operators.h b/cpp/src/compilation/pointers.h
similarity index 69%
rename from cpp/src/compilation/operators.h
rename to cpp/src/compilation/pointers.h
index 51a0448..1919bfb 100644
--- a/cpp/src/compilation/operators.h
+++ b/cpp/src/compilation/pointers.h
@@ -1,46 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: operators.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on April 8, 2017, 1:33 PM
*/
/**
* \file operators.h
* \brief Helpers to compile various operators
*/
#ifndef OPERATORS_H
#define OPERATORS_H
#include "pass/compilepass.h"
namespace llvm{
class Value;
}
-namespace xreate{ namespace pointerarithmetic{
+namespace xreate{ namespace pointers{
/** \brief Pointer arithmetic operators */
class PointerArithmetic{
public:
/** \brief Pointer arithmetic operator */
static llvm::Value* add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl);
};
-} //end of pointerarithmetic namespace
-
-/** \brief Struct update operators */
-class StructUpdate{
-public:
-
- /** \brief Struct update operator */
- static llvm::Value* add(const Expression& left, llvm::Value *leftRaw, const Expression& right, compilation::Context context, const std::string& hintVarDecl);
-} ;
+} //end of pointers namespace
} //namespace xreate
#endif /* OPERATORS_H */
diff --git a/cpp/src/compilation/polymorph.cpp b/cpp/src/compilation/polymorph.cpp
index 97e654b..900c71c 100644
--- a/cpp/src/compilation/polymorph.cpp
+++ b/cpp/src/compilation/polymorph.cpp
@@ -1,50 +1,68 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 9, 2018, 6:04 PM
*/
#include "compilation/polymorph.h"
using namespace std;
namespace xreate{
namespace polymorph{
-PolymorphFnInvocation::PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
- std::list<ManagedFnPtr> calleeSpecializations,
- CompilePass* pass,
- PolymorphQuery* query,
- LLVMLayer* llvm,
- latereasoning::LateReasoningCompiler* compiler)
-: __selector(selector), __calleeSpecializations(calleeSpecializations),
-__pass(pass), __query(query), __llvm(llvm), __compiler(compiler) { }
-
-llvm::Value*
-PolymorphFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
- std::map<Selector, ManagedFnPtr> dictSelectors;
- for(ManagedFnPtr specialization : __calleeSpecializations) {
- dictSelectors.emplace(specialization->guard, specialization);
+//PolymorphFnInvocation::PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
+// std::list<ManagedFnPtr> calleeSpecializations,
+// CompilePass* pass,
+// PolymorphQuery* query,
+// LLVMLayer* llvm,
+// latereasoning::LateReasoningCompiler* compiler)
+//: __selector(selector), __calleeSpecializations(calleeSpecializations),
+//__pass(pass), __query(query), __llvm(llvm), __compiler(compiler) { }
+//
+//llvm::Value*
+//PolymorphFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
+// std::map<Selector, ManagedFnPtr> dictSelectors;
+// for(ManagedFnPtr specialization : __calleeSpecializations) {
+// dictSelectors.emplace(specialization->guard, specialization);
+// }
+//
+// compilation::IBruteFunction* specAny = __pass->getFunctionUnit(__calleeSpecializations.front());
+// return __compiler->compileAutoExpand(
+// __selector,
+// specAny->prepareResult(),
+// hintDecl,
+// [this, &args, hintDecl, &dictSelectors](const Gringo::Symbol & selectorRaw) {
+// const Expression & selectorE = __query->getValue(selectorRaw);
+// assert(dictSelectors.count(selectorE) && "Inappropriate specialization guard");
+// compilation::BruteFnInvocation* invoc = new compilation::BruteFnInvocation(
+// __pass->getFunctionUnit(dictSelectors.at(selectorE))->compile(),
+// __llvm);
+//
+// return invoc->operator()(move(args), hintDecl);
+// });
+//}
+
+bool isFnGuarded(const std::string& fn, const AST& root){
+ const std::list<ManagedFnPtr>& specs = root.getFnSpecializations(fn);
+
+ //Extern function
+ if(specs.size() == 0){
+ return false;
+ }
+
+ //No other specializations. Check if it has no guard
+ if(specs.size() == 1){
+ if(!specs.front()->guard.isValid()){
+ return false;
}
+ }
- compilation::IFunctionUnit* specAny = __pass->getFunctionUnit(__calleeSpecializations.front());
- return __compiler->compileAutoExpand(
- __selector,
- specAny->prepareResult(),
- hintDecl,
- [this, &args, hintDecl, &dictSelectors](const Gringo::Symbol & selectorRaw) {
- const Expression & selectorE = __query->getValue(selectorRaw);
- assert(dictSelectors.count(selectorE) && "Inappropriate specialization guard");
- compilation::BruteFnInvocation* invoc = new compilation::BruteFnInvocation(
- __pass->getFunctionUnit(dictSelectors.at(selectorE))->compile(),
- __llvm);
-
- return invoc->operator()(move(args), hintDecl);
- });
-}
-}
+ return true;
}
+
+}}
diff --git a/cpp/src/compilation/polymorph.h b/cpp/src/compilation/polymorph.h
index 71194d6..5180719 100644
--- a/cpp/src/compilation/polymorph.h
+++ b/cpp/src/compilation/polymorph.h
@@ -1,103 +1,161 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on October 7, 2017
*/
/**
* \file src/compilation/polymorph.h
* \brief Polymorphism-aware compilation routines
*/
#ifndef POLYMORPHCOMPILER_H
#define POLYMORPHCOMPILER_H
#include "pass/compilepass.h"
#include "query/polymorph.h"
#include "compilation/latetranscend.h"
#include "compilation/targetinterpretation.h"
+#include "analysis/utils.h"
+#include "aux/expressions.h"
namespace xreate{
namespace polymorph{
-typedef Expression Selector;
+//typedef Expression Selector;
/** \brief An instance of \ref compilation::IFnInvocation to manage polymorphic functions invocation*/
-class PolymorphFnInvocation: public compilation::IFnInvocation{
-public:
- PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
- std::list<ManagedFnPtr> calleeSpecializations,
- CompilePass* pass,
- PolymorphQuery* query,
- LLVMLayer* llvm,
- latereasoning::LateReasoningCompiler* compiler);
-
- llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
-
-private:
- latereasoning::LateAnnotation __selector;
- std::list<ManagedFnPtr> __calleeSpecializations;
-
- CompilePass* __pass;
- PolymorphQuery* __query;
- LLVMLayer* __llvm;
- latereasoning::LateReasoningCompiler* __compiler;
-} ;
+//class PolymorphFnInvocation: public compilation::IFnInvocation{
+//public:
+// PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
+// std::list<ManagedFnPtr> calleeSpecializations,
+// CompilePass* pass,
+// PolymorphQuery* query,
+// LLVMLayer* llvm,
+// latereasoning::LateReasoningCompiler* compiler);
+//
+// llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
+//
+//private:
+// latereasoning::LateAnnotation __selector;
+// std::list<ManagedFnPtr> __calleeSpecializations;
+//
+// CompilePass* __pass;
+// PolymorphQuery* __query;
+// LLVMLayer* __llvm;
+// latereasoning::LateReasoningCompiler* __compiler;
+//} ;
/**
- * \brief Polymorphism aware \ref xreate::compilation::ICodeScopeUnit decorator
- * \implements xreate::compilation::ICodeScopeUnit
+ * \brief Polymorphism aware \ref xreate::compilation::IBruteScope decorator
+ * \implements xreate::compilation::IBruteScope
*/
+
+bool isFnGuarded(const std::string& fn, const AST& root);
+
template <class Parent>
-class PolymorphCodeScopeUnit: public Parent{
+class PolymorphBruteScopeDecorator: public Parent{
public:
- PolymorphCodeScopeUnit(const CodeScope * const codeScope,
- compilation::IFunctionUnit* f,
- CompilePass* compilePass)
+ PolymorphBruteScopeDecorator(const CodeScope * const codeScope,
+ compilation::IBruteFunction* f,
+ CompilePass* compilePass)
: Parent(codeScope, f, compilePass){ }
protected:
compilation::IFnInvocation*
findFunction(const Expression& opCall) override{
- // //Check does invocation require guards satisfaction
- const std::string& nameCallee = opCall.getValueString();
- const std::list<ManagedFnPtr>& specializations =
- Parent::pass->man->root->getFunctionSpecializations(nameCallee);
+ LLVMLayer* llvm = Parent::pass->man->llvm;
+ AST* ast = Parent::pass->man->root;
+ TranscendLayer* transcend = Parent::pass->man->transcend;
- //Extern function
- if(specializations.size() == 0){
+ //Check does invocation require guards satisfaction
+ const std::string& calleeName = opCall.getValueString();
+ if(!isFnGuarded(calleeName, *ast)){
return Parent::findFunction(opCall);
}
- //No other specializations. Check if it has no guard
- if(specializations.size() == 1){
- if(!specializations.front()->guard.isValid()){
- return Parent::findFunction(opCall);
- }
- }
-
//Several specializations
PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (
Parent::pass->man->transcend->getQuery(QueryId::PolymorphQuery));
- const latereasoning::LateAnnotation& selector = query->get(opCall);
- compilation::Context ctx{this, Parent::function, Parent::pass};
- interpretation::InterpretationScope* scopeIntrpr =
- Parent::pass->targetInterpretation->transformContext(ctx);
- latereasoning::LateReasoningCompiler* compiler
- = new latereasoning::LateReasoningCompiler(dynamic_cast<interpretation::InterpretationFunction*> (scopeIntrpr->function), ctx);
+ //Fill up a dict of all possible specializations
+ const std::list<ManagedFnPtr>& specs = ast->getFnSpecializations(calleeName);
+ std::map<std::string, ManagedFnPtr> dictSpecializations;
+ for(ManagedFnPtr specFn : specs) {
+ const TypeAnnotation& specT = specFn->guard.type;
+ assert(specFn->guard.isValid());
+ assert(specT.__operator == TypeOperator::VARIANT);
+
+ unsigned int variantId = specFn->guard.getValueDouble();
+ std::string specStr = specT.fields.at(variantId);
+ dictSpecializations.emplace(specStr, specFn);
+ }
+
+ auto supply = query->getFnSupply(ASTSite{opCall.id});
+ Gringo::Symbol supplyRaw = std::get<0>(supply);
+ ExpandedType supplyT = std::get<1>(supply);
+ Expression supplyE = analysis::representTransExpression(supplyRaw, supplyT, transcend);
+
+ const std::string& specStr = supplyT->fields.at(supplyE.getValueDouble());
+ ManagedFnPtr specFn = dictSpecializations.at(specStr);
+ const ExpandedType supplyDataT = ast->expandType(supplyT->__operands.at(supplyE.getValueDouble()));
- return new PolymorphFnInvocation(selector, specializations, Parent::pass,
- query, Parent::pass->man->llvm, compiler);
+ compilation::BruteFnInvocation* fnInvocDefault = new compilation::BruteFnInvocation(
+ Parent::pass->getFunctionUnit(specFn)->compile(), llvm
+ );
+ if (!supplyDataT->isValid()){
+ return fnInvocDefault;
+ }
+
+ const Expression& supplyDataE = getVariantData(supplyE, supplyT);
+ llvm::Value* supplyDataRaw = Parent::process(supplyDataE);
+ return new compilation::HiddenArgsFnInvocation({supplyDataRaw}, fnInvocDefault);
}
} ;
+template <class Parent>
+class PolymorphBruteFnDecorator: public Parent{
+public:
+ PolymorphBruteFnDecorator(ManagedFnPtr f, CompilePass *p): Parent(f, p){}
+
+protected:
+ std::vector<llvm::Type *>
+ prepareSignature() override {
+ std::vector<llvm::Type *> &&signature = Parent::prepareSignature();
+ if (!Parent::function->guard.isValid()) return signature;
+
+ AST* ast = Parent::pass->man->root;
+ unsigned int guardDataId = signature.size() + 1;
+ const Expression& guardE = Parent::function->guard;
+ assert(guardE.op == Operator::VARIANT);
+
+ const ExpandedType guardT = ast->expandType(guardE.type.__operands.at(guardE.getValueDouble()));
+ if (!guardT->isValid()) return signature;
+ if (!guardE.bindings.size()) return signature;
+ assert(guardE.bindings.size() == 1);
+
+ std::string guardArgName = guardE.bindings.at(0);
+ llvm::Type *guardTRaw = Parent::pass->man->llvm->toLLVMType(guardT);
+
+ Expression argBindE;
+ argBindE.type = guardT;
+
+ Parent::function->addBinding(
+ Atom<Identifier_t>(std::move(guardArgName)),
+ std::move(argBindE),
+ guardDataId
+ );
+ signature.push_back(guardTRaw);
+ return signature;
+ }
+};
+
}
} //end of xreate::polymorph
#endif /* POLYMORPHCOMPILER_H */
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index eef0aae..a41bac5 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,626 +1,648 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetinterpretation.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 29, 2016, 6:45 PM
*/
/**
* \file targetinterpretation.h
* \brief Interpretation support. See more details on [Interpretation](/d/concepts/interpretation/)
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
#include "analysis/typeinference.h"
#include "llvmlayer.h"
-#include "compilation/scopedecorators.h"
-#include "compilation/interpretation-instructions.h"
+#include "compilation/decorators.h"
+#include "compilation/i12ninst.h"
+#include "compilation/intrinsics.h"
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <csignal>
using namespace std;
using namespace xreate::compilation;
namespace xreate{
namespace interpretation{
const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
CodeScope*
InterpretationScope::processOperatorIf(const Expression& expression) {
const Expression& exprCondition = process(expression.getOperands()[0]);
if (exprCondition == EXPRESSION_TRUE) {
return expression.blocks.front();
}
return expression.blocks.back();
}
CodeScope*
InterpretationScope::processOperatorSwitch(const Expression& expression) {
const Expression& exprCondition = process(expression.operands[0]);
bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT;
//TODO check that one and only one case variant is appropriate
for (size_t size = expression.operands.size(), i = flagHasDefault ? 2 : 1; i < size; ++i) {
const Expression& exprCase = process(expression.operands[i]);
if (function->getScope((const CodeScope*) exprCase.blocks.front())->processScope() == exprCondition) {
return exprCase.blocks.back();
}
}
if (flagHasDefault) {
const Expression& exprCaseDefault = expression.operands[1];
return exprCaseDefault.blocks.front();
}
assert(false && "Switch has no appropriate variant");
return nullptr;
}
CodeScope*
InterpretationScope::processOperatorSwitchVariant(const Expression& expression) {
- const Expression& condition = process(expression.operands.at(0));
- assert(condition.op == Operator::VARIANT);
- const string& identCondition = expression.bindings.front();
-
- Expression opExpected(Atom<Number_t>(condition.getValueDouble()));
- auto itFoundValue = std::find(++expression.operands.begin(), expression.operands.end(), opExpected);
- assert(itFoundValue != expression.operands.end());
-
- int indexBlock = itFoundValue - expression.operands.begin() - 1;
- auto blockFound = expression.blocks.begin();
- std::advance(blockFound, indexBlock);
-
- InterpretationScope* scopeI12n = function->getScope(*blockFound);
-
- if(condition.operands.size()) {
- const Expression& value = condition.operands.at(0);
- scopeI12n->overrideBindings({
- {value, identCondition}
- });
- }
-
- return *blockFound;
+ const ExpandedType& conditionT = function->__pass->man->root->getType(expression.operands.at(0));
+ const Expression& conditionE = process(expression.operands.at(0));
+ assert(conditionE.op == Operator::VARIANT);
+ const string& aliasS = expression.bindings.front();
+
+ unsigned caseExpectedId = (int) conditionE.getValueDouble();
+ auto itFoundValue = std::find_if(++expression.operands.begin(), expression.operands.end(), [caseExpectedId](const auto& caseActualE){
+ return (unsigned) caseActualE.getValueDouble() == caseExpectedId;
+ });
+ assert(itFoundValue != expression.operands.end());
+
+ int caseScopeId = itFoundValue - expression.operands.begin() - 1;
+ auto caseScopeRef = expression.blocks.begin();
+ std::advance(caseScopeRef, caseScopeId);
+ InterpretationScope* scopeI12n = function->getScope(*caseScopeRef);
+
+ if(conditionE.operands.size()) {
+ Expression valueE(Operator::LIST, {});
+ valueE.operands = conditionE.operands;
+ valueE.bindings = conditionT->__operands.at(caseExpectedId).fields;
+
+ scopeI12n->overrideBindings({
+ {valueE, aliasS}
+ });
+ };
+
+ return *caseScopeRef;
}
llvm::Value*
-InterpretationScope::processLate(const InterpretationOperator& op, const Expression& expression, const Context& context) {
+InterpretationScope::processLate(const InterpretationOperator& op, const Expression& expression, const Context& context, const std::string& hintAlias) {
switch(op) {
case IF_INTERPRET_CONDITION:
{
CodeScope* scopeResult = processOperatorIf(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_INTERPRET_CONDITION:
{
CodeScope* scopeResult = processOperatorSwitch(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_VARIANT:
{
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
- const Expression& condition = expression.operands.at(0);
- const Expression& valueCondition = process(condition);
+ const Expression& condCrudeE = expression.operands.at(0);
+ const Expression& condE = process(condCrudeE);
const string identCondition = expression.bindings.front();
auto scopeCompilation = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeResult));
- if(valueCondition.operands.size()) {
+ if(condE.operands.size()) {
//override value
Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult};
scopeCompilation->overrideDeclarations({
- {symbCondition, Expression(valueCondition.operands.at(0))}}
+ {symbCondition, Expression(condE.operands.at(0))}}
);
//set correct type for binding:
- TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast);
- int conditionIndex = valueCondition.getValueDouble();
+ TypeAnnotation typeVariant = function->__pass->man->root->getType(condCrudeE);
+ int conditionIndex = condE.getValueDouble();
ScopedSymbol symbolInternal = scopeResult->getSymbol(identCondition);
scopeResult->__declarations[symbolInternal].bindType(typeVariant.__operands.at(conditionIndex));
}
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_LATE:
{
- latereasoning::LateReasoningCompiler compiler(dynamic_cast<InterpretationFunction*>(this->function), context);
- return compiler.processSwitchLateStatement(expression, "");
+ return nullptr;
+// latereasoning::LateReasoningCompiler compiler(dynamic_cast<InterpretationFunction*>(this->function), context);
+// return compiler.processSwitchLateStatement(expression, "");
}
case FOLD_INTERPRET_INPUT:
{
- //initialization
- const Expression& exprInput = process(expression.getOperands()[0]);
- assert(exprInput.op == Operator::LIST);
-
- CodeScope* scopeBody = expression.blocks.front();
-
- const string& nameEl = expression.bindings[0];
- Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
- const std::string& idAccum = expression.bindings[1];
- llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
-
- InterpretationScope* intrBody = function->getScope(scopeBody);
- auto unitBody = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeBody));
-
- const std::vector<Expression> elementsInput = exprInput.getOperands();
-
- for(size_t i = 0; i < elementsInput.size(); ++i) {
- const Expression& exprElement = elementsInput[i];
-
- intrBody->overrideBindings({
- {exprElement, nameEl}
- });
- unitBody->overrideDeclarations({
- {symbEl, exprElement}
- }); //resets unitBody
- unitBody->bindArg(rawAccum, string(idAccum));
+ //initialization
+ const Expression& containerE = process(expression.getOperands().at(0));
+ const TypeAnnotation& accumT = expression.type;
+ assert(containerE.op == Operator::LIST);
+ CodeScope* bodyScope = expression.blocks.front();
+ const string& elAlias = expression.bindings[0];
+ Symbol elS{ScopedSymbol{bodyScope->__identifiers.at(elAlias), versions::VERSION_NONE}, bodyScope};
+ const std::string& accumAlias = expression.bindings[1];
+ llvm::Value* accumRaw = context.scope->process(expression.getOperands().at(1), accumAlias, accumT);
+
+ InterpretationScope* bodyI12n = function->getScope(bodyScope);
+ auto bodyBrute = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(bodyScope));
+ const std::vector<Expression>& containerVec = containerE.getOperands();
+
+ for(size_t i = 0; i < containerVec.size(); ++i) {
+ const Expression& elE = containerVec[i];
+
+ bodyI12n->overrideBindings({
+ {elE, elAlias}
+ });
+ bodyBrute->overrideDeclarations({
+ {elS, elE}
+ }); //resets bodyBrute
+ bodyBrute->bindArg(accumRaw, string(accumAlias));
- rawAccum = unitBody->compile();
- }
+ accumRaw = bodyBrute->compile();
+ accumRaw->getType()->print(llvm::outs());
+ llvm::outs() << "\n\n";
+ }
- return rawAccum;
+ return accumRaw;
}
// case FOLD_INF_INTERPRET_INOUT:
// {
// }
//TODO refactor as InterpretationCallStatement class
case CALL_INTERPRET_PARTIAL:
{
const std::string &calleeName = expression.getValueString();
- ICodeScopeUnit* scopeUnitSelf = context.scope;
- ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName);
- const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee);
+ IBruteScope* scopeUnitSelf = context.scope;
+ ManagedFnPtr callee = this->function->__pass->man->root->findFunction(calleeName);
+ const I12nFunctionSpec& calleeData = FunctionInterpretationHelper::getSignature(callee);
std::vector<llvm::Value *> argsActual;
- PIFSignature sig;
+ PIFnSignature sig;
sig.declaration = callee;
for(size_t no = 0, size = expression.operands.size(); no < size; ++no) {
const Expression& op = expression.operands[no];
if (calleeData.signature.at(no) == INTR_ONLY) {
sig.bindings.push_back(process(op));
continue;
}
argsActual.push_back(scopeUnitSelf->process(op));
}
- TargetInterpretation* man = dynamic_cast<TargetInterpretation*> (this->function->man);
+ TargetInterpretation* man = dynamic_cast<TargetInterpretation*> (this->function->__pass);
PIFunction* pifunction = man->getFunction(move(sig));
llvm::Function* raw = pifunction->compile();
boost::scoped_ptr<BruteFnInvocation> statement(new BruteFnInvocation(raw, man->pass->man->llvm));
return (*statement)(move(argsActual));
}
case QUERY_LATE:
{
- return IntrinsicQueryInstruction(
- dynamic_cast<InterpretationFunction*>(this->function))
- .processLate(expression, context);
+ return nullptr;
+// return IntrinsicQueryInstruction(
+// dynamic_cast<InterpretationFunction*>(this->function))
+// .processLate(expression, context);
}
default: break;
}
assert(false && "Unknown late interpretation operator");
return nullptr;
}
llvm::Value*
-InterpretationScope::compile(const Expression& expression, const Context& context) {
+InterpretationScope::compile(const Expression& expression, const Context& context, const std::string& hintAlias) {
const InterpretationData& data = Attachments::get<InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE) {
- return processLate(data.op, expression, context);
+ return processLate(data.op, expression, context, hintAlias);
}
Expression result = process(expression);
- return context.scope->process(result);
+ return context.scope->process(result, hintAlias);
}
Expression
InterpretationScope::process(const Expression& expression) {
#ifndef NDEBUG
if (expression.tags.count("bpoint")) {
std::raise(SIGINT);
}
#endif
- PassManager* man = (static_cast<TargetInterpretation*> (function->man))->pass->man;
+ PassManager* man = function->__pass->man;
switch (expression.__state) {
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return Parent::processSymbol(s);
}
case Expression::COMPOUND:
break;
default: assert(false);
}
switch (expression.op) {
case Operator::EQU:
{
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_TRUE;
return EXPRESSION_FALSE;
}
case Operator::NE:
{
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_FALSE;
return EXPRESSION_TRUE;
}
case Operator::LOGIC_AND:
{
assert(expression.operands.size() == 1);
return process (expression.operands[0]);
}
// case Operator::LOGIC_OR:
case Operator::CALL:
{
const std::string &fnName = expression.getValueString();
- ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
- InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst);
+ ManagedFnPtr fnAst = man->root->findFunction(fnName);
+ InterpretationFunction* fnUnit = this->function->__pass->getFunction(fnAst);
vector<Expression> args;
args.reserve(expression.getOperands().size());
for(size_t i = 0, size = expression.getOperands().size(); i < size; ++i) {
args.push_back(process(expression.getOperands()[i]));
}
return fnUnit->process(args);
}
case Operator::CALL_INTRINSIC:
{
- assert(false && "Unknown intrinsic");
+ const Expression& opCallIntrCrude = expression;
+ vector<Expression> argsActual;
+ argsActual.reserve(opCallIntrCrude.getOperands().size());
+ for(const auto& op: opCallIntrCrude.getOperands()) {
+ argsActual.push_back(process(op));
+ }
+
+ Expression opCallIntr(Operator::CALL_INTRINSIC, {});
+ opCallIntr.setValueDouble(opCallIntrCrude.getValueDouble());
+ opCallIntr.operands = argsActual;
+
+ compilation::IntrinsicCompiler compiler(man);
+ return compiler.interpret(opCallIntr);
}
case Operator::QUERY:
{
- return IntrinsicQueryInstruction(dynamic_cast<InterpretationFunction*>(this->function))
- .process(expression);
+ return Expression();
+// return IntrinsicQueryInstruction(dynamic_cast<InterpretationFunction*>(this->function))
+// .process(expression);
}
case Operator::QUERY_LATE:
{
assert(false && "Can't be interpretated");
return Expression();
}
case Operator::IF:
{
CodeScope* scopeResult = processOperatorIf(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH:
{
CodeScope* scopeResult = processOperatorSwitch(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH_VARIANT:
{
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::VARIANT:
{
- if(!expression.operands.size()) return expression;
+ Expression result{Operator::VARIANT, {}};
+ result.setValueDouble(expression.getValueDouble());
- Expression variantData = process(expression.operands[0]);
- Expression result{Operator::VARIANT, {variantData}};
- result.setValueDouble(expression.getValueDouble());
- return result;
+ for(const Expression& op: expression.operands){
+ result.operands.push_back(process(op));
+ }
+
+ return result;
}
case Operator::INDEX:
{
- Expression exprData = process(expression.operands[0]);
+ Expression aggrE = process(expression.operands[0]);
- for (size_t keyId = 1; keyId < expression.operands.size(); ++keyId) {
- const Expression& exprKey = process(expression.operands[keyId]);
+ for (size_t keyId = 1; keyId < expression.operands.size(); ++keyId) {
+ const Expression& keyE = process(expression.operands[keyId]);
- if (exprKey.__state == Expression::STRING) {
- const string& key = exprKey.getValueString();
- assert(exprData.__indexBindings.count(key));
- size_t idxKey = exprData.__indexBindings.at(key);
-
- exprData = Expression(exprData.operands.at(idxKey));
- continue;
- }
-
- if (exprKey.__state == Expression::NUMBER) {
- int key = exprKey.getValueDouble();
- exprData = Expression(exprData.operands[key]);
- continue;
+ if (keyE.__state == Expression::STRING) {
+ const string& fieldExpectedS = keyE.getValueString();
+ unsigned fieldId;
+ for(fieldId = 0; fieldId < aggrE.bindings.size(); ++fieldId){
+ if (aggrE.bindings.at(fieldId) == fieldExpectedS){break;}
}
+ assert(fieldId < aggrE.bindings.size());
+ aggrE = Expression(aggrE.operands.at(fieldId));
+ continue;
+ }
- assert(false && "Inappropriate key");
+ if (keyE.__state == Expression::NUMBER) {
+ int opId = keyE.getValueDouble();
+ aggrE = Expression(aggrE.operands.at(opId));
+ continue;
}
- return exprData;
+ assert(false && "Inappropriate key");
+ }
+
+ return aggrE;
}
case Operator::FOLD:
{
const Expression& exprInput = process(expression.getOperands()[0]);
const Expression& exprInit = process(expression.getOperands()[1]);
const std::string& argEl = expression.bindings[0];
const std::string& argAccum = expression.bindings[1];
InterpretationScope* body = function->getScope(expression.blocks.front());
Expression accum = exprInit;
for(size_t size = exprInput.getOperands().size(), i = 0; i < size; ++i) {
body->overrideBindings({
{exprInput.getOperands()[i], argEl},
{accum, argAccum}
});
accum = body->processScope();
}
return accum;
}
case Operator::LIST:
case Operator::LIST_RANGE:
{
Expression result(expression.op,{});
result.operands.resize(expression.operands.size());
result.bindings = expression.bindings;
- result.__indexBindings = expression.__indexBindings;
int keyId = 0;
for(const Expression& opCurrent : expression.operands) {
result.operands[keyId++] = process(opCurrent);
}
return result;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
InterpretationFunction*
-TargetInterpretation::getFunction(IFunctionUnit* unit) {
+TargetInterpretation::getFunction(IBruteFunction* unit) {
if (__dictFunctionsByUnit.count(unit)) {
return __dictFunctionsByUnit.at(unit);
}
InterpretationFunction* f = new InterpretationFunction(unit->function, this);
__dictFunctionsByUnit.emplace(unit, f);
assert(__functions.emplace(unit->function.id(), f).second);
return f;
}
PIFunction*
-TargetInterpretation::getFunction(PIFSignature&& sig) {
+TargetInterpretation::getFunction(PIFnSignature&& sig) {
auto f = __pifunctions.find(sig);
if (f != __pifunctions.end()) {
return f->second;
}
- PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this);
+ PIFunction* result = new PIFunction(PIFnSignature(sig), __pifunctions.size(), this);
__pifunctions.emplace(move(sig), result);
- assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
+ assert(__dictFunctionsByUnit.emplace(result->fnRaw, result).second);
return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c) {
return this->getFunction(c.function)->getScope(c.scope->scope);
}
llvm::Value*
-TargetInterpretation::compile(const Expression& expression, const Context& ctx) {
- return transformContext(ctx)->compile(expression, ctx);
+TargetInterpretation::compile(const Expression& expression, const Context& ctx, const std::string& hintAlias) {
+ return transformContext(ctx)->compile(expression, ctx, hintAlias);
}
InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
: Function<TargetInterpretation>(function, target) { }
Expression
InterpretationFunction::process(const std::vector<Expression>& args) {
InterpretationScope* body = getScope(__function->__entry);
list<pair<Expression, string>> bindings;
for(size_t i = 0, size = args.size(); i < size; ++i) {
bindings.push_back(make_pair(args.at(i), body->scope->__bindings.at(i)));
}
body->overrideBindings(bindings);
return body->processScope();
}
// Partial function interpretation
-typedef BasicFunctionUnit PIFunctionUnitParent;
+typedef BasicBruteFunction BruteFunction;
-class PIFunctionUnit : public PIFunctionUnitParent{
+class PIBruteFunction : public BruteFunction{
public:
-
- PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
- : PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) { }
+ PIBruteFunction(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
+ : BruteFunction(f, p), argumentsActual(move(arguments)), __id(id) { }
protected:
-
std::vector<llvm::Type*>
prepareSignature() override {
- LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm;
- AST* ast = PIFunctionUnitParent::pass->man->root;
- CodeScope* entry = PIFunctionUnitParent::function->__entry;
+ LLVMLayer* llvm = BruteFunction::pass->man->llvm;
+ AST* ast = BruteFunction::pass->man->root;
+ CodeScope* entry = BruteFunction::function->__entry;
std::vector<llvm::Type*> signature;
for(size_t no : argumentsActual) {
VNameId argId = entry->__identifiers.at(entry->__bindings.at(no));
ScopedSymbol arg{argId, versions::VERSION_NONE};
signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type)));
}
return signature;
}
llvm::Function::arg_iterator
prepareBindings() override{
- CodeScope* entry = PIFunctionUnitParent::function->__entry;
- ICodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
- llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
+ CodeScope* entry = BruteFunction::function->__entry;
+ IBruteScope* entryCompilation = BruteFunction::getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = BruteFunction::raw->arg_begin();
for(size_t no : argumentsActual) {
ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, arg);
fargsI->setName(entry->__bindings.at(no));
++fargsI;
}
return fargsI;
}
virtual std::string
prepareName() override {
- return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
+ return BruteFunction::prepareName() + "_" + std::to_string(__id);
}
private:
std::set<size_t> argumentsActual;
size_t __id;
} ;
-PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
-: InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) {
- const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration);
+PIFunction::PIFunction(PIFnSignature&& sig, size_t id, TargetInterpretation* target)
+: InterpretationFunction(sig.declaration, target), instance(move(sig)) {
+ const I12nFunctionSpec& functionData = FunctionInterpretationHelper::getSignature(instance.declaration);
std::set<size_t> argumentsActual;
for (size_t no = 0, size = functionData.signature.size(); no < size; ++no) {
if (functionData.signature.at(no) != INTR_ONLY) {
argumentsActual.insert(no);
}
}
- functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass);
- CodeScope* entry = signatureInstance.declaration->__entry;
- auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(functionUnit->getEntry());
+ fnRaw = new PIBruteFunction(instance.declaration, move(argumentsActual), id, target->pass);
+ CodeScope* entry = instance.declaration->__entry;
+ auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(fnRaw->getEntry());
InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry);
list<pair<Expression, std::string>> bindingsPartial;
list<pair<Symbol, Expression>> declsPartial;
for(size_t no = 0, sigNo = 0, size = entry->__bindings.size(); no < size; ++no) {
if(functionData.signature.at(no) == INTR_ONLY) {
- bindingsPartial.push_back({signatureInstance.bindings[sigNo], entry->__bindings[no]});
+ bindingsPartial.push_back({instance.bindings[sigNo], entry->__bindings[no]});
VNameId argId = entry->__identifiers.at(entry->__bindings[no]);
Symbol argSymbol{ScopedSymbol
{argId, versions::VERSION_NONE}, entry};
- declsPartial.push_back({argSymbol, signatureInstance.bindings[sigNo]});
+ declsPartial.push_back({argSymbol, instance.bindings[sigNo]});
++sigNo;
}
}
entryIntrp->overrideBindings(bindingsPartial);
entryUnit->overrideDeclarations(declsPartial);
}
llvm::Function*
PIFunction::compile() {
- llvm::Function* raw = functionUnit->compile();
+ llvm::Function* raw = fnRaw->compile();
return raw;
}
-bool operator<(const PIFSignature& lhs, const PIFSignature& rhs) {
+bool operator<(const PIFnSignature& lhs, const PIFnSignature& rhs) {
if (lhs.declaration.id() != rhs.declaration.id()) {
return lhs.declaration.id() < rhs.declaration.id();
}
return lhs.bindings < rhs.bindings;
}
-bool operator<(const PIFSignature& lhs, PIFunction * const rhs) {
- return lhs < rhs->signatureInstance;
+bool operator<(const PIFnSignature& lhs, PIFunction * const rhs) {
+ return lhs < rhs->instance;
}
-bool operator<(PIFunction * const lhs, const PIFSignature& rhs) {
- return lhs->signatureInstance < rhs;
+bool operator<(PIFunction * const lhs, const PIFnSignature& rhs) {
+ return lhs->instance < rhs;
}
}
}
/** \class xreate::interpretation::InterpretationFunction
*
* Holds list of xreate::interpretation::InterpretationScope 's focused on interpretation of individual code scopes
*
* There is particulat subclass PIFunction intended to represent partially interpreted functions.
*\sa TargetInterpretation, [Interpretation Concept](/d/concepts/interpretation/)
*/
/** \class xreate::interpretation::TargetInterpretation
*
* TargetInterpretation is executed during compilation and is intended to preprocess eligible for interpretation parts of a source code.
*
* Keeps a list of InterpretationFunction / PIFunction that represent interpretation for an individual functions.
*
* There is \ref InterpretationScopeDecorator that embeds interpretation to an overall compilation process.
* \sa InterpretationPass, compilation::Target, [Interpretation Concept](/d/concepts/interpretation/)
*
*/
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 8ff000b..99c4089 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,133 +1,132 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetstatic.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H
#include "ast.h"
#include "pass/compilepass.h"
#include "compilation/targets.h"
#include "pass/interpretationpass.h"
#include "transcendlayer.h"
namespace xreate{ namespace interpretation{
class TargetInterpretation;
class InterpretationScope;
class InterpretationFunction;
}}
namespace xreate{ namespace compilation{
template <>
struct TargetInfo<interpretation::TargetInterpretation> {
typedef Expression Result;
typedef interpretation::InterpretationScope Scope;
typedef interpretation::InterpretationFunction Function;
};
}}
namespace xreate{ namespace interpretation{
/** \brief Encapsulates interpretation of a single code scope */
class InterpretationScope: public compilation::Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(const CodeScope* scope, compilation::Function<TargetInterpretation>* f): Parent(scope, f) {}
Expression process(const Expression& expression) override;
- llvm::Value* compile(const Expression& expression, const compilation::Context& context);
+ llvm::Value* compile(const Expression& expression, const compilation::Context& context, const std::string& hintAlias);
private:
- llvm::Value* processLate(const InterpretationOperator& op, const Expression& expression, const compilation::Context& context);
+ llvm::Value* processLate(const InterpretationOperator& op, const Expression& expression, const compilation::Context& context, const std::string& hintAlias);
//llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
CodeScope* processOperatorSwitchVariant(const Expression& expression);
};
/** \brief Encapsulates interpretation of a single function */
class InterpretationFunction: public compilation::Function<TargetInterpretation>{
public:
InterpretationFunction(const ManagedFnPtr& function, compilation::Target<TargetInterpretation>* target);
Expression process(const std::vector<Expression>& args);
};
/** \brief Signature of a partially interpreted function */
-struct PIFSignature{
+struct PIFnSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
-class PIFunctionUnit;
+class PIBruteFunction;
/** \brief Encapsulates partially interpreted function */
class PIFunction: public InterpretationFunction{
public:
- PIFunctionUnit* functionUnit;
- PIFSignature signatureInstance;
+ PIBruteFunction* fnRaw;
+ PIFnSignature instance;
- PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
+ PIFunction(PIFnSignature&& sig, size_t id, TargetInterpretation* target);
llvm::Function* compile();
};
-bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
-bool operator<(PIFunction* const lhs, const PIFSignature& rhs);
+bool operator<(const PIFnSignature& lhs, PIFunction* const rhs);
+bool operator<(PIFunction* const lhs, const PIFnSignature& rhs);
/** \brief Encapsulates interpretation process based on analysis results from \ref InterpretationPass
* \extends compilation::Target
* \sa InterpretationPass
*/
class TargetInterpretation: public compilation::Target<TargetInterpretation>{
-public:
- TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}
+ typedef compilation::Target<TargetInterpretation> Parent;
- //target:
-public:
- InterpretationFunction* getFunction(compilation::IFunctionUnit* unit);
- PIFunction* getFunction(PIFSignature&& sig);
+public:
+ TargetInterpretation(PassManager *man, CompilePass* passCompilation): Parent(man), pass(passCompilation){}
+ InterpretationFunction* getFunction(compilation::IBruteFunction* unit);
+ PIFunction* getFunction(PIFnSignature&& sig);
private:
- std::map<PIFSignature, PIFunction*> __pifunctions;
- std::map<compilation::IFunctionUnit*, InterpretationFunction*> __dictFunctionsByUnit;
+ std::map<PIFnSignature, PIFunction*> __pifunctions;
+ std::map<compilation::IBruteFunction*, InterpretationFunction*> __dictFunctionsByUnit;
- //self:
+ //self:
public:
- CompilePass* pass;
- llvm::Value* compile(const Expression& expression, const compilation::Context& ctx);
- InterpretationScope* transformContext(const compilation::Context& c);
+ CompilePass* pass;
+ llvm::Value* compile(const Expression& expression, const compilation::Context& ctx, const std::string& hintAlias);
+ InterpretationScope* transformContext(const compilation::Context& c);
private:
};
/**\brief Interpretation-aware Code Scope decorator
- * \extends xreate::compilation::ICodeScopeUnit
+ * \extends xreate::compilation::IBruteScope
*/
template<class Parent>
class InterpretationScopeDecorator: public Parent{
public:
- InterpretationScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+ InterpretationScopeDecorator(const CodeScope* const codeScope, compilation::IBruteFunction* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
- virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl){
+ virtual llvm::Value* process(const Expression& expr, const std::string& hintAlias, const TypeAnnotation& expectedT = TypeAnnotation()){
const InterpretationData& data = Attachments::get<InterpretationData>(expr, {ANY, NONE});
bool flagInterpretationEligible = (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
if (flagInterpretationEligible){
compilation::Context ctx{this, this->function, this->pass};
- return Parent::pass->targetInterpretation->compile(expr, ctx);
+ return Parent::pass->targetInterpretation->compile(expr, ctx, hintAlias);
}
- return Parent::process(expr, hintVarDecl);
+ return Parent::process(expr, hintAlias, expectedT);
}
};
}} //end of xreate:: interpretation
#endif /* TARGETSTATIC_H */
\ No newline at end of file
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
index 9a0b8cd..ebf5bd1 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,223 +1,208 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetabstract.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
/**
* \file
* \brief Compilation targets infrastructure
*/
#ifndef TARGETABSTRACT_H
#define TARGETABSTRACT_H
+class Function;
+
#include "ast.h"
+#include "pass/ipass.h"
+//#include "targetinterpretation.h"
#include <boost/optional.hpp>
#include <map>
#include <list>
namespace xreate{
namespace compilation{
-template <typename ConcreteTarget>
+template <typename ConcreteTargetTag>
struct TargetInfo{
- //typedef Result
- //typedef Function
- //typedef Scope
+//public:
+// typedef Result
+// typedef Function
+// typedef Scope
};
template<typename ConcreteTarget>
class Function;
template<typename ConcreteTarget>
class Target;
-template<typename ConcreteTarget>
+template<typename ConcreteTargetTag>
class Scope{
- typedef typename TargetInfo<ConcreteTarget>::Scope Self;
+ typedef typename TargetInfo<ConcreteTargetTag>::Scope Self;
public:
const CodeScope* scope;
- Function<ConcreteTarget>* function = 0;
+ Function<ConcreteTargetTag>* function = 0;
- typename TargetInfo<ConcreteTarget>::Result
+ typename TargetInfo<ConcreteTargetTag>::Result
processSymbol(const Symbol& s){
const CodeScope* scope = s.scope;
Self* self = function->getScope(scope);
if(self->__bindings.count(s.identifier)){
return self->__bindings[s.identifier];
}
const Expression& declaration = CodeScope::getDefinition(s, true);
if(!declaration.isDefined()){
assert(false); //for bindings there should be result already
}
return self->__bindings[s.identifier] = self->process(declaration);
}
- typename TargetInfo<ConcreteTarget>::Result
+ typename TargetInfo<ConcreteTargetTag>::Result
processScope(){
return process(scope->getBody());
}
- // typename TargetInfo<ConcreteTarget>::Result
- // processFunction(typename TargetInfo<ConcreteTarget>::Function* fnRemote, const std::vector<typename TargetInfo<ConcreteTarget>::Result>& args){
- // Scope<ConcreteTarget> scopeRemote = fnRemote->getScope(fnRemote->__function->__entry);
- //
- // if (scopeRemote->raw){
- // return scopeRemote->raw;
- // }
- //
- // return fnRemote->process(args);
- // }
-
- virtual typename TargetInfo<ConcreteTarget>::Result
+ virtual typename TargetInfo<ConcreteTargetTag>::Result
process(const Expression& expression) = 0;
- Scope(const CodeScope* codeScope, Function<ConcreteTarget>* f)
+ Scope(const CodeScope* codeScope, Function<ConcreteTargetTag>* f)
: scope(codeScope), function(f){ }
virtual
~Scope(){ }
void
- overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTarget>::Result, std::string>> bindings){
- std::list < std::pair<typename TargetInfo<ConcreteTarget>::Result, ScopedSymbol>> bindingsSymbols;
+ overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTargetTag>::Result, std::string>> bindings){
+ std::list < std::pair<typename TargetInfo<ConcreteTargetTag>::Result, ScopedSymbol>> bindingsSymbols;
for(auto entry: bindings){
assert(scope->__identifiers.count(entry.second));
ScopedSymbol id{scope->__identifiers.at(entry.second), versions::VERSION_NONE};
bindingsSymbols.push_back(std::make_pair(entry.first, id));
}
overrideBindings(bindingsSymbols);
}
void
- overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTarget>::Result, ScopedSymbol>> bindings){
+ overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTargetTag>::Result, ScopedSymbol>> bindings){
reset();
for(auto entry: bindings){
__bindings[entry.second] = entry.first;
}
}
bool
isBindingDefined(const ScopedSymbol& id){
return __bindings.count(id);
}
void
registerChildScope(std::shared_ptr<Self> scope){
__childScopes.push_back(scope);
}
void
reset(){
__bindings.clear();
__childScopes.clear();
}
protected:
- std::map<ScopedSymbol, typename TargetInfo<ConcreteTarget>::Result> __bindings;
+ std::map<ScopedSymbol, typename TargetInfo<ConcreteTargetTag>::Result> __bindings;
std::list<std::shared_ptr<Self>> __childScopes;
};
-template<typename ConcreteTarget>
+template<typename ConcreteTargetTag>
class Function{
- typedef typename TargetInfo<ConcreteTarget>::Result Result;
- typedef typename TargetInfo<ConcreteTarget>::Scope ConcreteScope;
+ typedef typename TargetInfo<ConcreteTargetTag>::Result Result;
+ typedef typename TargetInfo<ConcreteTargetTag>::Scope ConcreteScope;
public:
-
- Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
- : man(target), __function(function){ }
-
- virtual
- ~Function(){ };
+ Function(const ManagedFnPtr& function, Target<ConcreteTargetTag>* target)
+ : __pass(target), __function(function){ }
+ virtual ~Function(){ };
+ virtual Result process(const std::vector<Result>& args) = 0;
ConcreteScope*
getScope(const CodeScope * const scope){
if(__scopes.count(scope)){
auto result = __scopes.at(scope).lock();
if(result){
return result.get();
}
}
std::shared_ptr<ConcreteScope> unit(new ConcreteScope(scope, this));
if(scope->__parent != nullptr){
getScope(scope->__parent)->registerChildScope(unit);
} else{
assert(!__entryScope);
__entryScope = unit;
}
if(!__scopes.emplace(scope, unit).second){
__scopes[scope] = unit;
}
return unit.get();
}
- virtual Result
- process(const std::vector<Result>& args) = 0;
-
- Target<ConcreteTarget>* man = 0;
- ManagedFnPtr __function;
+ Target<ConcreteTargetTag>* __pass = 0;
protected:
+
+ ManagedFnPtr __function;
std::map<const CodeScope*, std::weak_ptr<ConcreteScope>> __scopes;
std::shared_ptr<ConcreteScope> __entryScope;
};
/** \brief Similar to xreate::IPass */
-template<typename ConcreteTarget>
-class Target{
- typedef typename TargetInfo<ConcreteTarget>::Function ConcreteFunction;
+template<typename ConcreteTargetTag>
+class Target: public IPass{
+ typedef typename TargetInfo<ConcreteTargetTag>::Function ConcreteFunction;
public:
+ Target(PassManager *manager): IPass(manager){ }
+ virtual ~Target(){
+ for(const auto& entry: __functions){
+ delete entry.second;
+ }
+ }
+ virtual void run() override {}
- Target(AST* root): ast(root){ }
-
- ConcreteFunction*
- getFunction(const ManagedFnPtr& function){
+ ConcreteFunction* getFunction(const ManagedFnPtr& function){
unsigned int id = function.id();
if(!__functions.count(id)){
ConcreteFunction* unit = new ConcreteFunction(function, this);
__functions.emplace(id, unit);
return unit;
}
return __functions.at(id);
}
- AST* ast;
-
- virtual
- ~Target(){
- for(const auto& entry: __functions){
- delete entry.second;
- }
- }
-
protected:
std::map<unsigned int, ConcreteFunction*> __functions;
};
}
}
#endif /* TARGETABSTRACT_H */
diff --git a/cpp/src/compilation/transformations.h b/cpp/src/compilation/transformations.h
index 2dcf8bc..fb33230 100644
--- a/cpp/src/compilation/transformations.h
+++ b/cpp/src/compilation/transformations.h
@@ -1,116 +1,116 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: transformations.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on March 25, 2017, 9:04 PM
*/
#ifndef TRANSFORMATIONS_H
#define TRANSFORMATIONS_H
#include "pass/compilepass.h"
namespace xreate { namespace compilation {
template <class TransformerType>
struct TransformerInfo {
//static const unsigned int id = 1; (current vacant id)
};
class Transformer{
public:
virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx)=0;
virtual ~Transformer(){};
};
class TransformationsManager {
public:
std::list<Transformer*> getRelevantTransformers(const Expression& expression);
template<class TransformerType>
void registerTransformer(const std::string& annotation, TransformerType* t){
const int id = TransformerInfo<TransformerType>::id;
assert(!__transformers.count(id));
__transformers[id] = t;
__subscriptions.emplace(annotation, id);
}
template<class TransformerType>
void unregisterTransformer(const std::string& annotation, TransformerType* t){
const unsigned int id = TransformerInfo<TransformerType>::id;
auto range = __subscriptions.equal_range(annotation);
const auto entry = make_pair(annotation, id);
__subscriptions.erase(std::find_if(range.first, range.second, [id](const auto& el){return el.second == id;}));
__transformers.erase(id);
}
template<class TransformerType>
TransformerType* update(TransformerType* newInstance){
const int id = TransformerInfo<TransformerType>::id;
Transformer* oldInstance = __transformers[id];
__transformers[id] = newInstance;
return static_cast<TransformerType*>(oldInstance);
}
template<class TransformerType>
bool exists(){
const int id = TransformerInfo<TransformerType>::id;
return __transformers.count(id);
}
template <class TransformerType>
TransformerType* get(){
const int id = TransformerInfo<TransformerType>::id;
return static_cast<TransformerType*>(__transformers.at(id));
}
private:
std::map<unsigned int, Transformer*> __transformers;
std::multimap<std::string, unsigned int> __subscriptions;
};
/**\brief Provides custom transformations during Code Scope compilation
- * \extends xreate::compilation::ICodeScopeUnit
+ * \extends xreate::compilation::IBruteScope
*/
template <class Parent>
class TransformationsScopeDecorator: public Transformer, public Parent {
// SCOPE DECORATOR PART
public:
- TransformationsScopeDecorator(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass)
+ TransformationsScopeDecorator(const CodeScope* const codeScope, IBruteFunction* f, CompilePass* compilePass)
: Parent(codeScope, f, compilePass){}
virtual llvm::Value*
process(const Expression& expr, const std::string& hintVarDecl=""){
llvm::Value* result = Parent::process(expr, hintVarDecl);
return transform(expr, result, Context{this, Parent::function, Parent::pass});
}
// TRANSFORMER PART
public:
virtual llvm::Value*
transform(const Expression& expression, llvm::Value* raw, const Context& ctx) {
llvm::Value* result = raw;
TransformationsManager* man = Parent::pass->managerTransformations;
if (expression.tags.size())
for (Transformer* handler: man->getRelevantTransformers(expression)){
result = handler->transform(expression, result, ctx);
}
return result;
}
};
} }
#endif /* TRANSFORMATIONS_H */
diff --git a/cpp/src/compilation/transformersaturation.cpp b/cpp/src/compilation/transformersaturation.cpp
index 4bf599c..7dfc263 100644
--- a/cpp/src/compilation/transformersaturation.cpp
+++ b/cpp/src/compilation/transformersaturation.cpp
@@ -1,84 +1,84 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* transformersaturation.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on March 25, 2017, 10:06 PM
*/
/**
* \file transformersaturation.h
* \brief Loop saturation support
*/
#include "transformersaturation.h"
#include "llvmlayer.h"
using namespace llvm;
namespace xreate { namespace compilation {
TransformerSaturation::TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager)
: man(manager), blockAllocation(allocationBlock){
if (man->exists<TransformerSaturation>()){
oldInstance = man->update(this);
} else {
man->registerTransformer("final", this);
}
}
TransformerSaturation::~TransformerSaturation(){
if (oldInstance) {
man->update(oldInstance);
} else {
man->unregisterTransformer("final", this);
}
}
llvm::Value*
TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
processBreak(ctx);
return raw;
}
void
TransformerSaturation::processBreak(const Context& ctx){
allocateFlag(ctx);
//show the saturation flag
- llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
+ llvm::IRBuilder<>& builder = ctx.pass->man->llvm->irBuilder;
llvm::Type* tyInt1 = llvm::Type::getInt1Ty(ctx.pass->man->llvm->llvmContext);
llvm::Constant* constTrue = llvm::ConstantInt::get(tyInt1, 1);
builder.CreateStore(constTrue, flagSaturation, true);
}
void
TransformerSaturation::allocateFlag(const Context& ctx){
//allocation of saturation flag
IRBuilder<> builder(blockAllocation, blockAllocation->getFirstInsertionPt());
llvm::Type* tyInt1 = llvm::Type::getInt1Ty(ctx.pass->man->llvm->llvmContext);
llvm::Constant* constTrue = llvm::ConstantInt::get(tyInt1, 1);
flagSaturation = builder.CreateAlloca(tyInt1, constTrue, "flagSaturation");
llvm::Constant* constFalse = llvm::ConstantInt::get(tyInt1, 0);
builder.CreateStore(constFalse, flagSaturation, true);
}
bool
TransformerSaturation::insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx){
if (!flagSaturation) return false;
- llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
+ llvm::IRBuilder<>& builder = ctx.pass->man->llvm->irBuilder;
builder.CreateCondBr(builder.CreateLoad(flagSaturation), blockExit, blockContinue);
return true;
}
} }
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 846d96c..930d6bf 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,242 +1,284 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* llvmlayer.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file llvmlayer.h
* \brief Bytecode generation
*/
#include "ast.h"
#include "llvmlayer.h"
+#include "analysis/typehints.h"
+
+#ifdef XREATE_ENABLE_EXTERN
#include "ExternLayer.h"
+#endif
+
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
+
#include <iostream>
#include <cmath>
using namespace llvm;
using namespace xreate;
+using namespace xreate::typehints;
using namespace std;
-LLVMLayer::LLVMLayer(AST* root)
-: llvmContext(),
-builder(llvmContext),
-ast(root),
-module(new llvm::Module(root->getModuleName(), llvmContext)) {
- layerExtern = new ExternLayer(this);
- layerExtern->init(root);
+LLVMLayer::LLVMLayer(AST *root)
+: llvmContext(),
+ irBuilder(llvmContext),
+ ast(root),
+ module(new llvm::Module(root->getModuleName(), llvmContext)){
+ llvm::InitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmPrinter();
+ llvm::EngineBuilder builder;
+ TargetMachine *target = builder.selectTarget();
+ module->setDataLayout(target->createDataLayout());
+
+#ifdef XREATE_ENABLE_EXTERN
+ layerExtern = new ExternLayer(this);
+ layerExtern->init(root);
+#endif
}
-void*
-LLVMLayer::getFunctionPointer(llvm::Function* function) {
- uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
- return (void*) entryAddr;
+void *
+LLVMLayer::getFunctionPointer(llvm::Function *function){
+ uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
+ return (void *) entryAddr;
}
void
-LLVMLayer::initJit() {
- std::string ErrStr;
- LLVMInitializeNativeTarget();
- llvm::InitializeNativeTargetAsmPrinter();
-
- llvm::EngineBuilder builder(std::unique_ptr<llvm::Module>(module.release()));
- jit.reset(builder
- .setEngineKind(llvm::EngineKind::JIT)
- .setErrorStr(&ErrStr)
- .setVerifyModules(true)
- .create()
- );
+LLVMLayer::initJit(){
+ std::string ErrStr;
+ llvm::EngineBuilder builder(std::unique_ptr<llvm::Module>(module.release()));
+ jit.reset(builder
+ .setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&ErrStr)
+ .setVerifyModules(true)
+ .create()
+ );
}
void
-LLVMLayer::print() {
- llvm::PassManager<llvm::Module> PM;
- PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
- llvm::AnalysisManager<llvm::Module> aman;
- PM.run(*module.get(), aman);
+LLVMLayer::print(){
+ llvm::PassManager<llvm::Module> PM;
+ PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
+ llvm::AnalysisManager<llvm::Module> aman;
+ PM.run(*module.get(), aman);
}
void
-LLVMLayer::moveToGarbage(void *o) {
- __garbage.push_back(o);
-}
-
-llvm::Type*
-LLVMLayer::toLLVMType(const ExpandedType& ty) const {
- std::map<int, llvm::StructType*> empty;
- return toLLVMType(ty, empty);
+LLVMLayer::moveToGarbage(void *o){
+ __garbage.push_back(o);
}
llvm::Type*
-LLVMLayer::toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const {
- TypeAnnotation t = ty;
- switch (t.__operator) {
- case TypeOperator::LIST_ARRAY:
- {
- assert(t.__operands.size() == 1);
-
- TypeAnnotation elTy = t.__operands.at(0);
- return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
+LLVMLayer::toLLVMType(const ExpandedType &ty) const{
+ TypeAnnotation t = ty;
+ switch(t.__operator){
+ case TypeOperator::ARRAY:{
+ //see ArrayIR::getRawT()
+ return nullptr;
}
- case TypeOperator::LIST_RECORD:
- {
- std::vector<llvm::Type*> pack_;
- pack_.reserve(t.__operands.size());
-
- std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
- [this, &conjuctions](const TypeAnnotation & t) {
- return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
- });
-
- llvm::ArrayRef<llvm::Type*> pack(pack_);
+ case TypeOperator::RECORD:{
+ std::vector<llvm::Type *> packVec;
+ packVec.reserve(t.__operands.size());
- //process recursive types:
- if (conjuctions.count(t.conjuctionId)) {
- auto result = conjuctions[t.conjuctionId];
- result->setBody(pack, false);
-
- return result;
- }
+ std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(packVec, packVec.end()),
+ [this](const TypeAnnotation &t){
+ return toLLVMType(ExpandedType(TypeAnnotation(t)));
+ });
- return llvm::StructType::get(llvmContext, pack, false);
+ llvm::ArrayRef<llvm::Type *> packArr(packVec);
+ return llvm::StructType::get(llvmContext, packArr, false);
};
- case TypeOperator::LINK:
- {
- llvm::StructType* conjuction = llvm::StructType::create(llvmContext);
- int id = t.conjuctionId;
+ case TypeOperator::REF:{
+ TypeAnnotation tyRef = t.__operands.at(0);
+ assert(tyRef.__operator == TypeOperator::ALIAS);
+ llvm::StructType *tyOpaqRaw = llvm::StructType::create(llvmContext, tyRef.__valueCustom);
+ llvm::PointerType *tyRefRaw = llvm::PointerType::get(tyOpaqRaw, 0);
- conjuctions.emplace(id, conjuction);
- return conjuction;
+ return tyRefRaw;
};
- case TypeOperator::CALL:
- {
- assert(false);
+ case TypeOperator::ALIAS:{
+#ifdef XREATE_ENABLE_EXTERN
+ //Look in extern types
+ clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
+ return layerExtern->toLLVMType(qt);
+#else
+ assert(false);
+#endif
};
- case TypeOperator::CUSTOM:
- {
- //Look in extern types
- clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
- return layerExtern->toLLVMType(qt);
- };
-
- //DEBT omit ID field in case of single variant.
- case TypeOperator::VARIANT:
- {
- /* Variant Type Layout:
- * {
- * id :: i8, Holds stored variant id
- * storage:: type of biggest variant
- * }
- */
- uint64_t sizeStorage = 0;
- llvm::Type* typStorageRaw = llvm::Type::getVoidTy(llvmContext);
- for(const TypeAnnotation& subtype : t.__operands) {
- llvm::Type* subtypeRaw = toLLVMType(ExpandedType(subtype), conjuctions);
- if (subtypeRaw->isVoidTy()) continue;
-
- uint64_t sizeSubtype = module->getDataLayout().getTypeStoreSize(subtypeRaw);
- if (sizeSubtype > sizeStorage) {
- sizeStorage = sizeSubtype;
- typStorageRaw = subtypeRaw;
- }
+ //DEBT omit ID field in case of single variant.
+ case TypeOperator::VARIANT:{
+ /* Variant Type Layout:
+ * {
+ * id :: i8, Holds stored variant id
+ * storage:: type of biggest variant
+ * }
+ */
+ uint64_t sizeStorage = 0;
+ llvm::Type *typStorageRaw = llvm::Type::getVoidTy(llvmContext);
+ for(const TypeAnnotation &subtype : t.__operands){
+ llvm::Type *subtypeRaw = toLLVMType(ExpandedType(subtype));
+ if(subtypeRaw->isVoidTy()) continue;
+
+ uint64_t sizeSubtype = module->getDataLayout().getTypeStoreSize(subtypeRaw);
+ if(sizeSubtype > sizeStorage){
+ sizeStorage = sizeSubtype;
+ typStorageRaw = subtypeRaw;
}
+ }
- std::vector<llvm::Type*> layout;
- layout.push_back(llvm::Type::getInt8Ty(llvmContext)); //id
+ std::vector<llvm::Type *> layout;
+ layout.push_back(llvm::Type::getInt8Ty(llvmContext)); //id
- const bool flagHoldsData = sizeStorage > 0;
- if (flagHoldsData) {
- layout.push_back(typStorageRaw); //storage
- }
-
- return llvm::StructType::get(llvmContext, llvm::ArrayRef<llvm::Type*>(layout));
- }
+ const bool flagHoldsData = sizeStorage > 0;
+ if(flagHoldsData){
+ layout.push_back(typStorageRaw); //storage
+ }
- case TypeOperator::NONE:
- {
- switch (t.__value) {
- case TypePrimitive::I32:
- case TypePrimitive::Int:
- case TypePrimitive::Num:
- return llvm::Type::getInt32Ty(llvmContext);
+ return llvm::StructType::get(llvmContext, llvm::ArrayRef<llvm::Type *>(layout));
+ }
+ case TypeOperator::NONE:{
+ switch(t.__value){
case TypePrimitive::Bool:
- return llvm::Type::getInt1Ty(llvmContext);
+ return llvm::Type::getInt1Ty(llvmContext);
case TypePrimitive::I8:
- return llvm::Type::getInt8Ty(llvmContext);
+ return llvm::Type::getInt8Ty(llvmContext);
+
+ case TypePrimitive::I32:
+ return llvm::Type::getInt32Ty(llvmContext);
case TypePrimitive::I64:
- return llvm::Type::getInt64Ty(llvmContext);
+ return llvm::Type::getInt64Ty(llvmContext);
+
+ case TypePrimitive::Int: {
+// IntBits hintSize;
+// if (existsSize(hintSize)){
+// return llvm::IntegerType::getIntNTy(llvmContext, hintSize.n);
+// }
+
+ TypesHelper helper(this);
+ return helper.getPreferredIntTy();
+ }
case TypePrimitive::Float:
- return llvm::Type::getDoubleTy(llvmContext);
+ return llvm::Type::getDoubleTy(llvmContext);
case TypePrimitive::String:
- return llvm::Type::getInt8PtrTy(llvmContext);
+ return llvm::Type::getInt8PtrTy(llvmContext);
case TypePrimitive::Invalid:
- return llvm::Type::getVoidTy(llvmContext);
+ return llvm::Type::getVoidTy(llvmContext);
default:
- assert(false);
- }
+ assert(false);
+ }
}
default:
- assert(false);
- }
+ assert(false);
+ }
- assert(false);
- return nullptr;
+ assert(false);
+ return nullptr;
}
bool
-TypeUtils::isStruct(const ExpandedType& ty) {
- const TypeAnnotation& t = ty.get();
+TypesHelper::isRecordT(const ExpandedType &ty){
+ const TypeAnnotation &t = ty.get();
- if (t.__operator == TypeOperator::LIST_RECORD) {
- return true;
- }
+ if(t.__operator == TypeOperator::RECORD){
+ return true;
+ }
- if (t.__operator != TypeOperator::CUSTOM) {
- return false;
- }
+ if(t.__operator != TypeOperator::ALIAS){
+ return false;
+ }
+#ifdef XREATE_ENABLE_EXTERN
clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
const clang::Type * raw = tqual.getTypePtr();
// TODO skip ALL the pointers until non-pointer type found
if (raw->isStructureType()) return true;
if (!raw->isAnyPointerType()) return false;
clang::QualType pointee = raw->getPointeeType();
return pointee->isStructureType();
+#else
+ assert(false);
+ return false;
+#endif
+}
+
+bool
+TypesHelper::isArrayT(const Expanded<TypeAnnotation>& ty){
+ const TypeAnnotation &t = ty.get();
+
+ if(t.__operator == TypeOperator::ARRAY){
+ return true;
+ }
+
+ return false;
}
bool
-TypeUtils::isPointer(const ExpandedType &ty) {
- if (ty.get().__operator != TypeOperator::CUSTOM) return false;
+TypesHelper::isPointerT(const ExpandedType &ty){
+ if(ty.get().__operator != TypeOperator::ALIAS) return false;
+#ifdef XREATE_ENABLE_EXTERN
clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
return llvm->layerExtern->isPointer(qt);
+#else
+ assert(false);
+ return false;
+#endif
}
+
+bool
+TypesHelper::isIntegerT(const Expanded<TypeAnnotation>& ty){
+return
+ (ty->__operator == TypeOperator::NONE) &&
+ ((ty->__value == TypePrimitive::Bool) ||
+ (ty->__value == TypePrimitive::I8) ||
+ (ty->__value == TypePrimitive::I32) ||
+ (ty->__value == TypePrimitive::I64) ||
+ (ty->__value == TypePrimitive::Int));
+}
+
+
std::vector<std::string>
-TypeUtils::getStructFields(const ExpandedType &t) {
- return (t.get().__operator == TypeOperator::LIST_RECORD)
- ? t.get().fields
- : llvm->layerExtern->getStructFields(
- llvm->layerExtern->lookupType(t.get().__valueCustom));
+TypesHelper::getRecordFields(const ExpandedType &t){
+#ifdef XREATE_ENABLE_EXTERN
+ return (t.get().__operator == TypeOperator::RECORD)
+ ? t.get().fields
+ : llvm->layerExtern->getStructFields(
+ llvm->layerExtern->lookupType(t.get().__valueCustom));
+#else
+ assert(t.get().__operator == TypeOperator::RECORD);
+ return t.get().fields;
+#endif
+}
+
+llvm::IntegerType *
+TypesHelper::getPreferredIntTy() const{
+ unsigned sizePreferred = llvm->module->getDataLayout().getLargestLegalIntTypeSizeInBits();
+ return llvm::IntegerType::getIntNTy(llvm->llvmContext, sizePreferred);
}
\ No newline at end of file
diff --git a/cpp/src/llvmlayer.h b/cpp/src/llvmlayer.h
index ab6938d..c93fc53 100644
--- a/cpp/src/llvmlayer.h
+++ b/cpp/src/llvmlayer.h
@@ -1,70 +1,73 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* llvmlayer.h
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef LLVMLAYER_H
#define LLVMLAYER_H
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"
namespace xreate {
class AST;
class ExternLayer;
class TypeAnnotation;
/** \brief A wrapper over LLVM toolchain to generate and execute bytecode */
class LLVMLayer {
public:
- LLVMLayer(AST* rootAST);
+ LLVMLayer(AST* rootAST);
- mutable llvm::LLVMContext llvmContext;
- llvm::IRBuilder<> builder;
- AST *ast = 0;
- ExternLayer *layerExtern =0;
- std::unique_ptr<llvm::Module> module;
- std::unique_ptr<llvm::ExecutionEngine> jit;
+ mutable llvm::LLVMContext llvmContext;
+ llvm::IRBuilder<> irBuilder;
+ AST *ast = 0;
+ ExternLayer *layerExtern =0;
+ std::unique_ptr<llvm::Module> module;
+ std::unique_ptr<llvm::ExecutionEngine> jit;
+ void moveToGarbage(void *o);
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
+ void print();
+ void* getFunctionPointer(llvm::Function* function);
- void moveToGarbage(void *o);
-
- llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
- void print();
- void* getFunctionPointer(llvm::Function* function);
-
- void initJit();
+ void initJit();
private:
- llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
- std::vector<void *> __garbage;
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
+ std::vector<void *> __garbage;
};
-struct TypeUtils {
- bool isStruct(const Expanded<TypeAnnotation>& ty);
- bool isPointer(const Expanded<TypeAnnotation>& ty);
- std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
+class TypesHelper {
+public:
+ bool isArrayT(const Expanded<TypeAnnotation>& ty);
+ bool isRecordT(const Expanded<TypeAnnotation>& ty);
+ bool isPointerT(const Expanded<TypeAnnotation>& ty);
+
+ bool isIntegerT(const Expanded<TypeAnnotation>& ty);
+ llvm::IntegerType* getPreferredIntTy() const;
+
+ std::vector<std::string> getRecordFields(const Expanded<TypeAnnotation>& t);
- TypeUtils(LLVMLayer*llvmlayer)
- : llvm(llvmlayer){}
+ TypesHelper(const LLVMLayer* llvmlayer): llvm(llvmlayer){}
- private:
- LLVMLayer* llvm;
+private:
+ const LLVMLayer* llvm;
};
}
#endif // LLVMLAYER_H
diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp
index ca196eb..40fa3c6 100644
--- a/cpp/src/modules.cpp
+++ b/cpp/src/modules.cpp
@@ -1,168 +1,168 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 22, 2017, 5:13 PM
*/
/**
* \file modules.h
* \brief Modules support
*/
#include "modules.h"
#include "modules/Parser.h"
#include "analysis/utils.h"
#include <clingo/clingocontrol.hh>
#include <boost/format.hpp>
#include <regex>
#include <boost/filesystem.hpp>
#include <fstream>
using namespace std;
namespace fs = boost::filesystem;
namespace xreate { namespace modules{
void
ModuleRecord::addRequest(const Expression& request){
__requests.push_back(request);
}
void
ModuleRecord::addControllerPath(const std::string& path){
__controllers.push_back(path);
}
void
ModuleRecord::addDiscoveryPath(const std::string& path){
__discoveryPaths.push_back(path);
}
void
ModuleRecord::addProperty(const Expression& prop){
__properties.push_back(prop);
}
void
ModulesSolver::loadControllers(const ModuleRecord& module){
for (const std::string& pathController: module.__controllers){
std::fstream fileContent(pathController);
__program << fileContent.rdbuf();
}
}
void
ModulesSolver::extractProperties(const ModuleRecord& module){
- const std::string atomProperty = "bind_module";
- boost::format formatProperty(atomProperty + "(\"%1%\", %2%).");
-
- for (const Expression& property: module.__properties){
- std::list<std::string> reprProp = xreate::analysis::compile(property);
- assert(reprProp.size()== 1);
-
- __program << (formatProperty % module.__path % reprProp.front())
- << std::endl;
- }
+// const std::string atomProperty = "bind_module";
+// boost::format formatProperty(atomProperty + "(\"%1%\", %2%).");
+//
+// for (const Expression& property: module.__properties){
+// std::list<std::string> reprProp = xreate::analysis::compile(property);
+// assert(reprProp.size()== 1);
+//
+// __program << (formatProperty % module.__path % reprProp.front())
+// << std::endl;
+// }
}
void
ModulesSolver::discoverModules(const ModuleRecord& moduleClient){
std::regex extXreate("\\.xreate$", std::regex::basic);
for(const std::string& path: moduleClient.__discoveryPaths){
for(fs::directory_entry e: fs::recursive_directory_iterator(path)) {
if (fs::is_regular_file(e.status())){
if (!std::regex_search(e.path().string(), extXreate)) continue;
FILE* script = fopen(e.path().c_str(), "r");
Scanner scanner(script);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Discovery errors");
parser.module.__path = e.path().c_str();
extractProperties(parser.module);
fclose(script);
}
}
}
}
void
ModulesSolver::extractRequirements(const ModuleRecord& module){
- const std::string atomQuery = "modules_require";
- boost::format formatProperty(atomQuery + "(\"%1%\", %2%).");
-
- for (const Expression& query: module.__requests){
- std::list<std::string> reprQuery = xreate::analysis::compile(query);
- assert(reprQuery.size()== 1);
-
- __program << (formatProperty % module.__path % reprQuery.front())
- << std::endl;
- }
+// const std::string atomQuery = "modules_require";
+// boost::format formatProperty(atomQuery + "(\"%1%\", %2%).");
+//
+// for (const Expression& query: module.__requests){
+// std::list<std::string> reprQuery = xreate::analysis::compile(query);
+// assert(reprQuery.size()== 1);
+//
+// __program << (formatProperty % module.__path % reprQuery.front())
+// << std::endl;
+// }
}
-void
+void
ModulesSolver::add(const std::string& base){
__program << base;
}
void
ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){
add(programBase);
extractRequirements(module);
extractProperties(module);
loadControllers(module);
discoverModules(module);
std::cout << __program.str() << std::endl;
}
std::list<std::string>
ModulesSolver::run(const ModuleRecord& module){
const std::string predicateResolution = "modules_resolution";
std::map<Expression, string> dictResolution;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
ctl.add("base", {}, __program.str());
ctl.ground({{"base", {}}}, nullptr);
ctl.solve([&predicateResolution, this, &dictResolution, &module](Gringo::Model const &model) {
for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
std::cout << atom << std::endl;
if (std::strcmp(atom.name().c_str(), predicateResolution.c_str())!=0) continue;
if (atom.arity() == 2){
auto resolution = TranscendLayer::parse<Expression, std::string>(atom);
dictResolution.emplace(get<0>(resolution), get<1>(resolution));
continue;
}
if (atom.arity() == 3){
auto resolution = TranscendLayer::parse<Expression, std::string, std::string>(atom);
if(get<2>(resolution) != module.__path) continue;
dictResolution.emplace(get<0>(resolution), get<1>(resolution));
continue;
}
assert(false && "Wrong resolution format");
}
return true;
}, {});
std::list<std::string> result;
for(const Expression& request: module.__requests){
assert(dictResolution.count(request) && "Can't find requested module");
result.push_back(dictResolution.at(request));
}
return result;
}
}} //namespace xreate::modules
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index 26b3195..2cd2d7a 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,101 +1,100 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file abstractpass.h
* \brief Infrastructure to iterate over AST to facilitate analysis and compilation.
*/
#include "abstractpass.h"
#include "attachments.h"
#include "xreatemanager.h"
using namespace std;
namespace xreate {
template<>
void defaultValue<void>(){}
void IPass::finish(){}
IPass::IPass(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
{
if (__visitedSymbols.isCached(symbol))
return;
__visitedSymbols.setCachedValue(symbol);
const Expression& declaration = CodeScope::getDefinition(symbol, true);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
process(declaration, context2, hintSymbol);
}
}
template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (expression.__state == Expression::COMPOUND){
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL){
processExpressionCall(expression, context);
}
return;
}
if (expression.__state == Expression::IDENT){
assert(context.scope);
processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
}
}
/**
* \class xreate::IPass
*
* An each pass has to have IPass interface to be controllable by \ref XreateManager.
* However in most cases users should inherit minimal useful implementation \ref xreate::AbstractPass
*
* \note It's usually expected that a custom pass publishes processing results by one of the following means:
* - xreate::Attachments for communicating with other passes
* - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
*
* \sa xreate::XreateManager, xreate::AbstractPass
*/
/**
* \class xreate::AbstractPass
*
* The class traverses the %AST in a minimally useful manner sparing clients from processing an every possible node manually.
* This way clients able to focus only on relevant nodes processing.
*
* The `Output` template parameter specifies the type of node processing result data.
*
* \note Automatically caches already visited nodes
*
* \note It's usually expected that a custom pass publishes processing results by one of the following means:
* - \ref xreate::Attachments for communicating with other passes
* - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
*
* \sa xreate::XreateManager, xreate::IPass, xreate::AST
- */
-
+ */
\ No newline at end of file
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index ea44e23..1d05360 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,206 +1,189 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
-#include "ast.h"
+#include "pass/ipass.h"
#include "xreatemanager.h"
-
-#include<iostream>
+#include "ast.h"
namespace xreate {
/** \brief Holds current position in the %AST during traverse*/
struct PassContext {
const CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext() {}
PassContext updateScope(const CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return context2;
}
~PassContext() {}
};
-/** \brief Interface for all passes to inherit. \ref xreate::PassManager holds a collection of passes to execute */
-class IPass {
-public:
- IPass(PassManager* manager);
-
- virtual ~IPass() {}
-
- /** \brief Executes pass */
- virtual void run() = 0;
-
- /** \brief Finalizes pass. Empty by default*/
- virtual void finish();
-
- PassManager* man;
-};
-
template<class Output>
Output
defaultValue();
template<>
void
defaultValue<void>();
/** \brief Stores processing results for the already visited nodes */
template<class Output>
class SymbolCache : private std::map<Symbol, Output> {
public:
bool isCached(const Symbol &symbol) {
return this->count(symbol);
}
Output setCachedValue(const Symbol &symbol, Output &&value) {
(*this)[symbol] = value;
return value;
}
Output getCachedValue(const Symbol &symbol) {
assert(this->count(symbol));
return this->at(symbol);
}
};
/** \brief Set of the already visited nodes */
template<>
class SymbolCache<void> : private std::set<Symbol> {
public:
bool isCached(const Symbol &symbol) {
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol &symbol) {
this->insert(symbol);
}
void getCachedValue(const Symbol &symbol) {
}
};
/** \brief Minimal \ref xreate::IPass implementation useful for many passes as the base class*/
template<class Output>
class AbstractPass : public IPass {
SymbolCache<Output> __visitedSymbols;
protected:
virtual Output processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol = "") {
if(__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
const Expression &declaration = CodeScope::getDefinition(symbol, true);
if(declaration.isDefined()) {
PassContext context2 = context.updateScope(symbol.scope);
Output &&result = process(declaration, context2, hintSymbol);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
Output processExpressionCall(const Expression &expression, PassContext context) {
const std::string &calleeName = expression.getValueString();
- std::list<ManagedFnPtr> callees = man->root->getFunctionSpecializations(calleeName);
+ std::list<ManagedFnPtr> callees = man->root->getFnSpecializations(calleeName);
//Determined specialization
if(callees.size() == 1 && callees.front()) {
return processFnCall(callees.front(), context);
}
//Several specializations or External Fn
return processFnCallUncertain(calleeName, callees, context);
}
SymbolCache<Output> &getSymbolCache() {
return __visitedSymbols;
}
public:
AbstractPass(PassManager* manager)
: IPass(manager) {}
/** \brief Processes function invocation instruction */
virtual Output processFnCall(ManagedFnPtr functionCallee, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes function invocation instruction in uncertain cases
* \details Executed when it's impossible statically determine which exactly function is invoked.
*/
virtual Output processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes Logic Rule */
virtual void process(ManagedRulePtr rule) {}
/** \brief Processes Function */
virtual Output process(ManagedFnPtr function) {
PassContext context;
context.function = function;
return process(function->getEntryScope(), context);
}
/** \brief Processes single CodeScope */
virtual Output process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl = "") {
context.scope = scope;
return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
}
//TODO expose Symbol instead of varDecl. Required by DFAPass.
/** \brief Processes single Expression */
virtual Output process(const Expression &expression, PassContext context, const std::string &varDecl = "") {
if(expression.__state == Expression::IDENT) {
assert(context.scope);
return processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
assert(false);
return defaultValue<Output>();
}
/** \brief Executes AST traverse */
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while(rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while(f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol);
template<>
void
AbstractPass<void>::process(const Expression &expression, PassContext context, const std::string &hintSymbol);
}
#endif
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 06049f2..65afc4b 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,788 +1,826 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* compilepass.cpp
*/
/**
* \file compilepass.h
* \brief Main compilation routine. See \ref xreate::CompilePass
*/
#include "compilepass.h"
#include "transcendlayer.h"
-#include <ast.h>
+#include "ast.h"
#include "llvmlayer.h"
-#include "query/containers.h"
-#include "compilation/containers.h"
-#include "ExternLayer.h"
-#include "compilation/targetinterpretation.h"
-#include "pass/versionspass.h"
-#include "compilation/scopedecorators.h"
-#include "compilation/operators.h"
-#include "compilation/latex.h"
+#include "compilation/decorators.h"
+#include "compilation/pointers.h"
#include "analysis/typeinference.h"
+#include "compilation/control.h"
+#include "compilation/demand.h"
+#include "analysis/resources.h"
+#ifdef XREATE_ENABLE_EXTERN
+ #include "ExternLayer.h"
+#endif
+
+#include "compilation/containers.h"
+#include "compilation/containers/arrays.h"
+
+#ifndef XREATE_CONFIG_MIN
+ #include "query/containers.h"
+
+ #include "pass/versionspass.h"
+ #include "compilation/targetinterpretation.h"
+#endif
+
#include <boost/optional.hpp>
#include <memory>
-#include <iostream>
using namespace std;
using namespace llvm;
namespace xreate{
namespace compilation{
+#define DEFAULT(x) (hintAlias.empty()? x: hintAlias)
+
std::string
-BasicFunctionUnit::prepareName() {
- AST* ast = IFunctionUnit::pass->man->root;
+BasicBruteFunction::prepareName() {
+ AST* ast = IBruteFunction::pass->man->root;
- string name = ast->getFunctionSpecializations(IFunctionUnit::function->__name).size() > 1 ?
- IFunctionUnit::function->__name + std::to_string(IFunctionUnit::function.id()) :
- IFunctionUnit::function->__name;
+ string name = ast->getFnSpecializations(IBruteFunction::function->__name).size() > 1 ?
+ IBruteFunction::function->__name + std::to_string(IBruteFunction::function.id()) :
+ IBruteFunction::function->__name;
return name;
}
std::vector<llvm::Type*>
-BasicFunctionUnit::prepareSignature() {
- LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
- AST* ast = IFunctionUnit::pass->man->root;
- CodeScope* entry = IFunctionUnit::function->__entry;
+BasicBruteFunction::prepareSignature() {
+ LLVMLayer* llvm = IBruteFunction::pass->man->llvm;
+ AST* ast = IBruteFunction::pass->man->root;
+ CodeScope* entry = IBruteFunction::function->__entry;
std::vector<llvm::Type*> signature;
std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
[llvm, ast, entry](const std::string & arg)->llvm::Type* {
assert(entry->__identifiers.count(arg));
ScopedSymbol argid{entry->__identifiers.at(arg), versions::VERSION_NONE};
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
});
return signature;
}
llvm::Type*
-BasicFunctionUnit::prepareResult() {
- LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
- AST* ast = IFunctionUnit::pass->man->root;
- CodeScope* entry = IFunctionUnit::function->__entry;
+BasicBruteFunction::prepareResult() {
+ LLVMLayer* llvm = IBruteFunction::pass->man->llvm;
+ AST* ast = IBruteFunction::pass->man->root;
+ CodeScope* entry = IBruteFunction::function->__entry;
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
-BasicFunctionUnit::prepareBindings() {
- CodeScope* entry = IFunctionUnit::function->__entry;
- ICodeScopeUnit* entryCompilation = IFunctionUnit::getScopeUnit(entry);
- llvm::Function::arg_iterator fargsI = IFunctionUnit::raw->arg_begin();
+BasicBruteFunction::prepareBindings() {
+ CodeScope* entry = IBruteFunction::function->__entry;
+ IBruteScope* entryCompilation = IBruteFunction::getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = IBruteFunction::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
ScopedSymbol argid{entry->__identifiers[arg], versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, argid);
fargsI->setName(arg);
++fargsI;
}
return fargsI;
}
-//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
-typedef latex::LatexBruteFunctionDecorator<
- compilation::BasicFunctionUnit>
-
- BruteFunctionDefault;
-
-ICodeScopeUnit::ICodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
+IBruteScope::IBruteScope(const CodeScope * const codeScope, IBruteFunction* f, CompilePass* compilePass)
: pass(compilePass), function(f), scope(codeScope), currentBlockRaw(nullptr) { }
llvm::Value*
BruteFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
if (calleeInfo) {
auto argsFormal = calleeInfo->args();
size_t sizeArgsF = std::distance(argsFormal.begin(), argsFormal.end());
assert(args.size() >= sizeArgsF);
assert(calleeInfo->isVarArg() || args.size() == sizeArgsF);
auto argFormal = argsFormal.begin();
for(size_t argId = 0; argId < args.size(); ++argId){
if(argFormal != argsFormal.end()){
args[argId] = typeinference::doAutomaticTypeConversion(
- args.at(argId), argFormal->getType(), llvm->builder);
+ args.at(argId), argFormal->getType(), llvm->irBuilder);
++argFormal;
}
}
}
//Do not name function call that returns Void.
std::string nameStatement = hintDecl;
if (calleeInfo->getReturnType()->isVoidTy()) {
nameStatement.clear();
}
- return llvm->builder.CreateCall(__calleeTy, __callee, args, nameStatement);
+ return llvm->irBuilder.CreateCall(__calleeTy, __callee, args, nameStatement);
}
-//DESABLEDFEATURE implement inlining
+llvm::Value*
+HiddenArgsFnInvocation::operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
+ args.insert(args.end(), __args.begin(), __args.end());
+ return __parent->operator ()(std::move(args), hintDecl);
+}
class CallStatementInline : public IFnInvocation{
public:
- CallStatementInline(IFunctionUnit* caller, IFunctionUnit* callee, LLVMLayer* l)
+ CallStatementInline(IBruteFunction* caller, IBruteFunction* callee, LLVMLayer* l)
: __caller(caller), __callee(callee), llvm(l) { }
llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
- //TOTEST inlining
- // CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
- // for(int i=0, size = args.size(); i<size; ++i) {
- // entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
- // }
- //
- //
- // return entryCompilation->compile();
-
return nullptr;
}
private:
- IFunctionUnit* __caller;
- IFunctionUnit* __callee;
+ IBruteFunction* __caller;
+ IBruteFunction* __callee;
LLVMLayer* llvm;
bool
isInline() {
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
} ;
-BasicCodeScopeUnit::BasicCodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
-: ICodeScopeUnit(codeScope, f, compilePass) { }
+BasicBruteScope::BasicBruteScope(const CodeScope * const codeScope, IBruteFunction* f, CompilePass* compilePass)
+: IBruteScope(codeScope, f, compilePass) { }
llvm::Value*
-BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar) {
+BasicBruteScope::processSymbol(const Symbol& s, std::string hintRetVar) {
Expression declaration = CodeScope::getDefinition(s);
const CodeScope* scopeExternal = s.scope;
- ICodeScopeUnit* scopeBruteExternal = ICodeScopeUnit::function->getScopeUnit(scopeExternal);
+ IBruteScope* scopeBruteExternal = IBruteScope::function->getScopeUnit(scopeExternal);
assert(scopeBruteExternal->currentBlockRaw);
llvm::Value* resultRaw;
- llvm::BasicBlock* blockOwn = pass->man->llvm->builder.GetInsertBlock();
+ llvm::BasicBlock* blockOwn = pass->man->llvm->irBuilder.GetInsertBlock();
if (scopeBruteExternal->currentBlockRaw == blockOwn) {
resultRaw = scopeBruteExternal->process(declaration, hintRetVar);
scopeBruteExternal->currentBlockRaw = currentBlockRaw =
- pass->man->llvm->builder.GetInsertBlock();
+ pass->man->llvm->irBuilder.GetInsertBlock();
} else {
- pass->man->llvm->builder.SetInsertPoint(scopeBruteExternal->currentBlockRaw);
+ pass->man->llvm->irBuilder.SetInsertPoint(scopeBruteExternal->currentBlockRaw);
resultRaw = scopeBruteExternal->processSymbol(s, hintRetVar);
- pass->man->llvm->builder.SetInsertPoint(blockOwn);
+ pass->man->llvm->irBuilder.SetInsertPoint(blockOwn);
}
return resultRaw;
}
IFnInvocation*
-BasicCodeScopeUnit::findFunction(const Expression& opCall) {
+BasicBruteScope::findFunction(const Expression& opCall) {
const std::string& calleeName = opCall.getValueString();
LLVMLayer* llvm = pass->man->llvm;
- const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionSpecializations(calleeName);
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFnSpecializations(calleeName);
- //if no specializations registered - check external function
- if (specializations.size() == 0) {
- llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
+#ifdef XREATE_ENABLE_EXTERN
+ //if no specializations registered - check external function
+ if (specializations.size() == 0) {
+ llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
- llvm::outs() << "Debug/External function: " << calleeName;
- external->getType()->print(llvm::outs(), true);
- llvm::outs() << "\n";
+ llvm::outs() << "Debug/External function: " << calleeName;
+ external->getType()->print(llvm::outs(), true);
+ llvm::outs() << "\n";
- return new BruteFnInvocation(external, llvm);
- }
+ return new BruteFnInvocation(external, llvm);
+ }
+#endif
//There should be only one specialization without any valid guards at this point
return new BruteFnInvocation(pass->getFunctionUnit(
pass->man->root->findFunction(calleeName))->compile(),
llvm);
}
//DISABLEDFEATURE transformations
// if (pass->transformations->isAcceptable(expr)){
// return pass->transformations->transform(expr, result, ctx);
// }
llvm::Value*
-BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl) {
-#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
- llvm::Value *left;
- llvm::Value *right;
+BasicBruteScope::process(const Expression& expr, const std::string& hintAlias, const TypeAnnotation& expectedT) {
+ llvm::Value *leftRaw;
+ llvm::Value *rightRaw;
LLVMLayer& l = *pass->man->llvm;
- xreate::compilation::AdvancedInstructions instructions = xreate::compilation::AdvancedInstructions({this, function, pass});
+ Context ctx{this, function, pass};
+ xreate::compilation::ControlIR controlIR = xreate::compilation::ControlIR({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::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]);
+ leftRaw = process(expr.operands[0]);
+ rightRaw = process(expr.operands[1]);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
{
- left = process(expr.operands[0]);
- Context context{this, function, pass};
-
- llvm::Value* resultSU = StructUpdate::add(expr.operands[0], left, expr.operands[1], context, DEFAULT("tmp_add"));
- if (resultSU) return resultSU;
-
- right = process(expr.operands[1]);
-
- llvm::Value* resultAddPA = pointerarithmetic::PointerArithmetic::add(left, right, context, DEFAULT("tmp_add"));
- if (resultAddPA) {
- return resultAddPA;
- }
-
- return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
- break;
+ return l.irBuilder.CreateAdd(leftRaw, rightRaw, DEFAULT("addv"));
}
case Operator::SUB:
- return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
+ return l.irBuilder.CreateSub(leftRaw, rightRaw, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
- return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
+ return l.irBuilder.CreateMul(leftRaw, rightRaw, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
- if (left->getType()->isIntegerTy()) return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
- if (left->getType()->isFloatingPointTy()) return l.builder.CreateFDiv(left, right, DEFAULT("tmp_div"));
+ if (leftRaw->getType()->isIntegerTy()) return l.irBuilder.CreateSDiv(leftRaw, rightRaw, DEFAULT("tmp_div"));
+ if (leftRaw->getType()->isFloatingPointTy()) return l.irBuilder.CreateFDiv(leftRaw, rightRaw, DEFAULT("tmp_div"));
break;
case Operator::EQU: {
- if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
- if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
+ if (leftRaw->getType()->isIntegerTy()) return l.irBuilder.CreateICmpEQ(leftRaw, rightRaw, DEFAULT("tmp_equ"));
+ if (leftRaw->getType()->isFloatingPointTy()) return l.irBuilder.CreateFCmpOEQ(leftRaw, rightRaw, DEFAULT("tmp_equ"));
const ExpandedType& leftT = pass->man->root->getType(expr.operands[0]);
- const ExpandedType& rightT = pass->man->root->getType(expr.operands[0]);
+ const ExpandedType& rightT = pass->man->root->getType(expr.operands[1]);
if(leftT->__operator == TypeOperator::VARIANT && rightT->__operator == TypeOperator::VARIANT){
- llvm::Type* selectorT = llvm::cast<llvm::StructType>(left->getType())->getElementType(0);
- llvm::Value* leftUnwapped = typeinference::doAutomaticTypeConversion(left, selectorT, l.builder);
- llvm::Value* rightUnwapped = typeinference::doAutomaticTypeConversion(right, selectorT, l.builder);
- return l.builder.CreateICmpEQ(leftUnwapped, rightUnwapped, DEFAULT("tmp_equ"));
+ llvm::Type* selectorT = llvm::cast<llvm::StructType>(leftRaw->getType())->getElementType(0);
+ llvm::Value* leftUnwapped = typeinference::doAutomaticTypeConversion(leftRaw, selectorT, l.irBuilder);
+ llvm::Value* rightUnwapped = typeinference::doAutomaticTypeConversion(rightRaw, selectorT, l.irBuilder);
+ return l.irBuilder.CreateICmpEQ(leftUnwapped, rightUnwapped, DEFAULT("tmp_equ"));
}
-
-
break;
}
case Operator::NE:
- return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
+ return l.irBuilder.CreateICmpNE(leftRaw, rightRaw, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
- return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
+ return l.irBuilder.CreateICmpSLT(leftRaw, rightRaw, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
- return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
+ return l.irBuilder.CreateICmpSLE(leftRaw, rightRaw, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
- return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
+ return l.irBuilder.CreateICmpSGT(leftRaw, rightRaw, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
- return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
+ return l.irBuilder.CreateICmpSGE(leftRaw, rightRaw, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
{
- left = process(expr.operands[0]);
+ leftRaw = process(expr.operands[0]);
ExpandedType leftTy = pass->man->root->getType(expr.operands[0]);
if (leftTy->__value == TypePrimitive::Bool){
- return l.builder.CreateNot(left, DEFAULT("tmp_not"));
+ return l.irBuilder.CreateNot(leftRaw, DEFAULT("tmp_not"));
} else {
- return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
+ return l.irBuilder.CreateNeg(leftRaw, DEFAULT("tmp_neg"));
}
break;
}
case Operator::CALL:
{
assert(expr.__state == Expression::COMPOUND);
shared_ptr<IFnInvocation> callee(findFunction(expr));
const std::string& nameCallee = expr.getValueString();
//prepare arguments
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression & operand) {
return process(operand);
}
);
return (*callee)(move(args), DEFAULT("res_" + nameCallee));
}
case Operator::IF:
{
- return instructions.compileIf(expr, DEFAULT("tmp_if"));
+ return controlIR.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
- return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
+ return controlIR.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOGIC_AND:
{
assert(expr.operands.size() == 1);
return process(expr.operands[0]);
}
- case Operator::LIST:
+ case Operator::LIST: //init record or array
{
- ExpandedType exprT = l.ast->getType(expr);
- bool flagIsArray;
-
- do {
- if (exprT->__operator == TypeOperator::CUSTOM){
- if (l.layerExtern->isArrayType(exprT->__valueCustom)){
- flagIsArray = true;
- break;
- }
-
- if (l.layerExtern->isRecordType(exprT->__valueCustom)){
- flagIsArray = false;
- break;
- }
-
- assert(false && "Inapproriate external type");
- }
-
- if (exprT->__operator != TypeOperator::LIST_ARRAY && exprT->__operator != TypeOperator::LIST_RECORD){
- assert(false && "Inapproriate type");
- }
-
- flagIsArray = exprT->__operator == TypeOperator::LIST_ARRAY;
-
- } while(false);
-
- if(flagIsArray){
- return instructions.compileListAsSolidArray(expr, DEFAULT("tmp_list"));
- }
-
- const std::vector<string> fieldsFormal = (exprT.get().__operator == TypeOperator::CUSTOM) ?
- l.layerExtern->getStructFields(l.layerExtern->lookupType(exprT.get().__valueCustom))
- : exprT.get().fields;
-
- std::map<std::string, size_t> indexFields;
- for (size_t i = 0, size = fieldsFormal.size(); i < size; ++i) {
- indexFields.emplace(fieldsFormal[i], i);
+ ExpandedType exprT = l.ast->getType(expr, expectedT);
+ TypesHelper helper(pass->man->llvm);
+
+ enum {RECORD, ARRAY} kind;
+ if (helper.isArrayT(exprT)){
+ kind = ARRAY;
+
+ } else if (helper.isRecordT(exprT)){
+ kind = RECORD;
+ } else {
+ assert(false && "Inapproriate type");
+ }
+
+ #ifdef XREATE_ENABLE_EXTERN
+ if (exprT->__operator == TypeOperator::ALIAS){
+ if (l.layerExtern->isArrayType(exprT->__valueCustom)){
+ flagIsArray = true;
+ break;
+ }
+
+ if (l.layerExtern->isRecordType(exprT->__valueCustom)){
+ flagIsArray = false;
+ break;
+ }
+
+ assert(false && "Inapproriate external type");
+ }
+ #endif
+
+ switch(kind){
+ case RECORD:{
+ const std::vector<string> fieldsFormal = helper.getRecordFields(exprT);
+ containers::RecordIR irRecords(ctx);
+ llvm::StructType *recordTRaw = llvm::cast<llvm::StructType>(l.toLLVMType(exprT));
+ llvm::Value *resultRaw = irRecords.init(recordTRaw);
+ return irRecords.update(resultRaw, exprT, expr);
}
- llvm::StructType* tyLiteralRaw = llvm::cast<llvm::StructType>(l.toLLVMType(exprT));
- llvm::Value* record = llvm::UndefValue::get(tyLiteralRaw);
-
- for (size_t i = 0; i < expr.operands.size(); ++i) {
- const Expression& operand = expr.operands.at(i);
- unsigned int fieldId = indexFields.at(expr.bindings.at(i));
- llvm::Value* result = process(operand);
- assert(result);
- record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
+ case ARRAY: {
+ std::unique_ptr<containers::IContainersIR> containerIR(
+ containers::IContainersIR::create(expr, expectedT, ctx));
+ llvm::Value* aggrRaw = containerIR->init(hintAlias);
+ return containerIR->update(aggrRaw, expr, hintAlias);
}
-
- return record;
+ }
+ break;
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::MAP:
{
assert(expr.blocks.size());
- return instructions.compileMapSolidOutput(expr, DEFAULT("map"));
+ return controlIR.compileMapSolidOutput(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
- return instructions.compileFold(expr, DEFAULT("fold"));
+ return controlIR.compileFold(expr, DEFAULT("fold"));
};
- case Operator::INF:
+ case Operator::FOLD_INF:
{
- return instructions.compileFoldInf(expr, DEFAULT("fold"));
+ return controlIR.compileFoldInf(expr, DEFAULT("fold"));
};
case Operator::INDEX:
{
- //TASK allow multiindex compilation
- assert(expr.operands.size() == 2);
- assert(expr.operands[0].__state == Expression::IDENT);
-
- const std::string& hintIdent = expr.operands[0].getValueString();
- Symbol s = Attachments::get<IdentifierSymbol>(expr.operands[0]);
- const ExpandedType& t2 = pass->man->root->getType(expr.operands[0]);
+ assert(expr.operands.size() > 1);
+
+ const Expression& aggrE = expr.operands[0];
+ const ExpandedType& aggrT = pass->man->root->getType(aggrE);
+ llvm::Value* aggrRaw = process(aggrE);
+ switch (aggrT->__operator) {
+ case TypeOperator::RECORD:
+ {
+ list<string> fieldsList;
+ for(auto opIt = ++expr.operands.begin(); opIt!=expr.operands.end(); ++opIt){
+ fieldsList.push_back(getIndexStr(*opIt));
+ }
- llvm::Value* aggr = processSymbol(s, hintIdent);
+ return controlIR.compileStructIndex(aggrRaw, aggrT, fieldsList);
+ };
- switch (t2.get().__operator) {
- case TypeOperator::LIST_RECORD: case TypeOperator::CUSTOM:
- {
- std::string idxField;
- const Expression& idx = expr.operands.at(1);
- switch (idx.__state) {
-
- //named struct field
- case Expression::STRING:
- idxField = idx.getValueString();
- break;
-
- //anonymous struct field
- case Expression::NUMBER:
- idxField = to_string((int) idx.getValueDouble());
- break;
-
- default:
- assert(false && "Wrong index for a struct");
+ 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.compileStructIndex(aggr, t2, idxField);
- };
+ std::unique_ptr<containers::IContainersIR> containersIR(
+ containers::IContainersIR::create(aggrE, expectedT, ctx)
+ );
- case TypeOperator::LIST_ARRAY:
- {
- std::vector<llvm::Value*> indexes;
- std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
- [this] (const Expression & op) {
- return process(op);
- }
- );
-
- return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
- };
+ containers::ArrayIR* arraysIR = static_cast<containers::ArrayIR*>(containersIR.get());
+ return arraysIR->get(aggrRaw, indexes, hintAlias);
+ };
- default:
- assert(false);
- }
+ default:
+ assert(false);
+ }
};
case Operator::CALL_INTRINSIC:
{
- const std::string op = expr.getValueString();
-
- if (op == "copy") {
- llvm::Value* result = process(expr.getOperands().at(0));
-
- auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
- llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
- decoratorVersions->processIntrinsicCopy(result, storage);
-
- return l.builder.CreateLoad(storage, hintVarDecl);
- }
+// const std::string op = expr.getValueString();
+//
+// if (op == "copy") {
+// llvm::Value* result = process(expr.getOperands().at(0));
+//
+// auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
+// llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
+// decoratorVersions->processIntrinsicCopy(result, storage);
+//
+// return l.irBuilder.CreateLoad(storage, hintAlias);
+// }
assert(false && "undefined intrinsic");
}
case Operator::QUERY:
case Operator::QUERY_LATE:
{
assert(false && "Should be processed by interpretation");
}
case Operator::VARIANT:
{
- const ExpandedType& typVariant = pass->man->root->getType(expr);
- llvm::Type* typVariantRaw = l.toLLVMType(typVariant);
- llvm::Type* typIdRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(0);
-
- uint64_t id = expr.getValueDouble();
- llvm::Value* variantRaw = llvm::UndefValue::get(typVariantRaw);
- variantRaw = l.builder.CreateInsertValue(variantRaw, llvm::ConstantInt::get(typIdRaw, id), llvm::ArrayRef<unsigned>({0}));
-
- const bool flagDoReference = expr.operands.size();
- if (flagDoReference) {
- const ExpandedType& subtyp = ExpandedType(typVariant->__operands.at(id));
- llvm::Type* subtypRaw = l.toLLVMType(subtyp);
- Attachments::put<TypeInferred>(expr.operands.at(0), subtyp);
- llvm::Value* subtypValue = process(expr.operands.at(0));
-
- llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
- llvm::Value* addrAsStorage = l.builder.CreateAlloca(typStorageRaw);
- llvm::Value* addrAsSubtyp = l.builder.CreateBitOrPointerCast(addrAsStorage, subtypRaw->getPointerTo());
-
- l.builder.CreateStore(subtypValue, addrAsSubtyp);
- llvm::Value* storageRaw = l.builder.CreateLoad(typStorageRaw, addrAsStorage);
- variantRaw = l.builder.CreateInsertValue(variantRaw, storageRaw, llvm::ArrayRef<unsigned>({1}));
- }
-
- return variantRaw;
+ const ExpandedType& typResult = pass->man->root->getType(expr);
+ llvm::Type* typResultRaw = l.toLLVMType(typResult);
+ llvm::Type* typIdRaw = llvm::cast<llvm::StructType>(typResultRaw)->getElementType(0);
+
+ uint64_t id = expr.getValueDouble();
+ llvm::Value* resultRaw = llvm::UndefValue::get(typResultRaw);
+ resultRaw = l.irBuilder.CreateInsertValue(resultRaw, llvm::ConstantInt::get(typIdRaw, id), llvm::ArrayRef<unsigned>({0}));
+
+ const ExpandedType& typVariant = ExpandedType(typResult->__operands.at(id));
+ llvm::Type* typVariantRaw = l.toLLVMType(typVariant);
+ llvm::Value* variantRaw = llvm::UndefValue::get(typVariantRaw);
+ assert(expr.operands.size() == typVariant->__operands.size() && "Wrong variant arguments count");
+ if (!typVariant->__operands.size()) return resultRaw;
+
+ for (unsigned int fieldId = 0; fieldId < expr.operands.size(); ++fieldId) {
+ const ExpandedType& typField = ExpandedType(typVariant->__operands.at(fieldId));
+ Attachments::put<TypeInferred>(expr.operands.at(fieldId), typField);
+ llvm::Value* fieldRaw = process(expr.operands.at(fieldId));
+ assert(fieldRaw);
+
+ variantRaw = l.irBuilder.CreateInsertValue(variantRaw, fieldRaw, llvm::ArrayRef<unsigned>({fieldId}));
+ }
+
+ llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typResultRaw)->getElementType(1);
+ llvm::Value* addrAsStorage = l.irBuilder.CreateAlloca(typStorageRaw);
+ llvm::Value* addrAsVariant = l.irBuilder.CreateBitOrPointerCast(addrAsStorage, typVariantRaw->getPointerTo());
+
+ l.irBuilder.CreateStore(variantRaw, addrAsVariant);
+ llvm::Value* storageRaw = l.irBuilder.CreateLoad(typStorageRaw, addrAsStorage);
+ resultRaw = l.irBuilder.CreateInsertValue(resultRaw, storageRaw, llvm::ArrayRef<unsigned>({1}));
+
+ return resultRaw;
}
case Operator::SWITCH_VARIANT:
{
- return instructions.compileSwitchVariant(expr, DEFAULT("tmpswitch"));
+ return controlIR.compileSwitchVariant(expr, DEFAULT("tmpswitch"));
}
case Operator::SWITCH_LATE:
{
assert(false && "Instruction's compilation should've been redirected to interpretation");
return nullptr;
}
case Operator::SEQUENCE:
{
- return instructions.compileSequence(expr);
+ return controlIR.compileSequence(expr);
}
case Operator::UNDEF:
{
- llvm::Type* typExprUndef = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
- return llvm::UndefValue::get(typExprUndef);
+ llvm::Type* typExprUndef = l.toLLVMType(pass->man->root->getType(expr, expectedT));
+ return llvm::UndefValue::get(typExprUndef);
+ }
+
+ case Operator::UPDATE:
+ {
+ TypesHelper helper(pass->man->llvm);
+ containers::RecordIR irRecords(ctx);
+
+ const Expression& aggrE = expr.operands.at(0);
+ const Expression& updE = expr.operands.at(1);
+ const ExpandedType& aggrT = pass->man->root->getType(aggrE);
+ llvm::Value* aggrRaw = process(aggrE);
+
+ if (helper.isRecordT(aggrT)){
+ return irRecords.update(aggrRaw, aggrT, updE);
+ }
+
+ if (helper.isArrayT(aggrT)){
+ if (updE.op == Operator::LIST_INDEX){
+
+ std::unique_ptr<containers::IContainersIR> containersIR(
+ containers::IContainersIR::create(aggrE, TypeAnnotation(), ctx
+ ));
+
+ return containersIR->update(aggrRaw, updE, hintAlias);
+ }
+ }
+
+ assert(false);
+ return nullptr;
}
case Operator::INVALID:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expr);
return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER:
{
- llvm::Type* typConst = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
+ llvm::Type* typConst = l.toLLVMType(pass->man->root->getType(expr, expectedT));
int literal = expr.getValueDouble();
if (typConst->isFloatingPointTy()) return llvm::ConstantFP::get(typConst, literal);
if (typConst->isIntegerTy()) return llvm::ConstantInt::get(typConst, literal);
assert(false && "Can't compile literal");
}
case Expression::STRING:
{
- return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
+ return controlIR.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
default:
{
break;
}
};
break;
default: break;
}
assert(false && "Can't compile expression");
return 0;
}
llvm::Value*
-BasicCodeScopeUnit::compile(const std::string& hintBlockDecl) {
+BasicBruteScope::compile(const std::string& hintBlockDecl) {
LLVMLayer* llvm = pass->man->llvm;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm->llvmContext, hintBlockDecl, function->raw);
- pass->man->llvm->builder.SetInsertPoint(block);
+ pass->man->llvm->irBuilder.SetInsertPoint(block);
}
- currentBlockRaw = pass->man->llvm->builder.GetInsertBlock();
+ currentBlockRaw = pass->man->llvm->irBuilder.GetInsertBlock();
Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
return processSymbol(symbScope);
}
-ICodeScopeUnit::~ICodeScopeUnit() { }
+IBruteScope::~IBruteScope() { }
-IFunctionUnit::~IFunctionUnit() { }
+IBruteFunction::~IBruteFunction() { }
llvm::Function*
-IFunctionUnit::compile() {
+IBruteFunction::compile() {
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
- llvm::IRBuilder<>& builder = llvm->builder;
+ llvm::IRBuilder<>& builder = llvm->irBuilder;
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareSignature();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result = getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
- builder.CreateRet(typeinference::doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
+ builder.CreateRet(typeinference::doAutomaticTypeConversion(result, expectedResultType, llvm->irBuilder));
if (blockCurrent) {
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
-ICodeScopeUnit*
-IFunctionUnit::getScopeUnit(const CodeScope * const scope) {
+IBruteScope*
+IBruteFunction::getScopeUnit(const CodeScope * const scope) {
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result) {
return result.get();
}
}
- std::shared_ptr<ICodeScopeUnit> unit(pass->buildCodeScopeUnit(scope, this));
+ std::shared_ptr<IBruteScope> unit(pass->buildCodeScopeUnit(scope, this));
if (scope->__parent != nullptr) {
auto parentUnit = Decorators<CachedScopeDecoratorTag>::getInterface(getScopeUnit(scope->__parent));
parentUnit->registerChildScope(unit);
} else {
__orphanedScopes.push_back(unit);
}
if (!__scopes.emplace(scope, unit).second) {
__scopes[scope] = unit;
}
return unit.get();
}
-ICodeScopeUnit*
-IFunctionUnit::getScopeUnit(ManagedScpPtr scope) {
+IBruteScope*
+IBruteFunction::getScopeUnit(ManagedScpPtr scope) {
return getScopeUnit(&*scope);
}
-ICodeScopeUnit*
-IFunctionUnit::getEntry() {
+IBruteScope*
+IBruteFunction::getEntry() {
return getScopeUnit(function->getEntryScope());
}
template<>
-compilation::IFunctionUnit*
+compilation::IBruteFunction*
CompilePassCustomDecorators<void, void>
::buildFunctionUnit(const ManagedFnPtr& function) {
return new BruteFunctionDefault(function, this);
}
template<>
-compilation::ICodeScopeUnit*
+compilation::IBruteScope*
CompilePassCustomDecorators<void, void>
-::buildCodeScopeUnit(const CodeScope * const scope, IFunctionUnit* function) {
+::buildCodeScopeUnit(const CodeScope * const scope, IBruteFunction* function) {
return new DefaultCodeScopeUnit(scope, function, this);
}
+std::string
+BasicBruteScope::getIndexStr(const Expression& index){
+ switch(index.__state){
+
+//named struct field
+ case Expression::STRING:
+ return index.getValueString();
+ break;
+
+//anonymous struct field
+ case Expression::NUMBER:
+ return to_string((int) index.getValueDouble());
+ break;
+
+ default:
+ assert(false && "Wrong index for a struct");
+ }
+ return "";
+}
+
} // end of compilation
-compilation::IFunctionUnit*
+compilation::IBruteFunction*
CompilePass::getFunctionUnit(const ManagedFnPtr& function) {
unsigned int id = function.id();
if (!functions.count(id)) {
- compilation::IFunctionUnit* unit = buildFunctionUnit(function);
+ compilation::IBruteFunction* unit = buildFunctionUnit(function);
functions.emplace(id, unit);
return unit;
}
return functions.at(id);
}
+void
+CompilePass::prepare(){
+ //Initialization:
+#ifndef XREATE_CONFIG_MIN
+#endif
+ managerTransformations = new xreate::compilation::TransformationsManager();
+ targetInterpretation = new interpretation::TargetInterpretation(man, this);
+}
+
void
CompilePass::run() {
- //Initialization:
- managerTransformations = new xreate::compilation::TransformationsManager();
- targetInterpretation = new interpretation::TargetInterpretation(this->man->root, this);
+ prepare();
- //Determine entry function:
- StaticModel model = man->transcend->query(Config::get("function-entry"));
- assert(model.size() && "Error: No entry function found");
- assert(model.size() == 1 && "Error: Ambiguous entry function");
+ //Determine entry function:
+ StaticModel model = man->transcend->query(analysis::FN_ENTRY_PREDICATE);
+ assert(model.size() && "Error: No entry function found");
+ assert(model.size() == 1 && "Error: Ambiguous entry function");
- string nameMain = std::get<0>(TranscendLayer::parse<std::string>(model.begin()->second));
- compilation::IFunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
+ string nameMain = std::get<0>(TranscendLayer::parse<std::string>(model.begin()->second));
+ compilation::IBruteFunction* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
- //Compilation itself:
- entry = unitMain->compile();
+ //Compilation itself:
+ entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction() {
assert(entry);
return entry;
}
void
CompilePass::prepareQueries(TranscendLayer* transcend) {
- transcend->registerQuery(new containers::Query(), QueryId::ContainersQuery);
- transcend->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
- transcend->registerQuery(new latex::LatexQuery(), QueryId::LatexQuery);
+#ifndef XREATE_CONFIG_MIN
+ transcend->registerQuery(new latex::LatexQuery(), QueryId::LatexQuery);
+#endif
+
+ transcend->registerQuery(new containers::Query(), QueryId::ContainersQuery);
+ transcend->registerQuery(new demand::DemandQuery(), QueryId::DemandQuery);
+ transcend->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
}
+
} //end of namespace xreate
/**
* \class xreate::CompilePass
* \brief The owner of the compilation process. Performs fundamental compilation activities along with the xreate::compilation's routines
*
* xreate::CompilePass traverses over xreate::AST tree and produces executable code.
* The pass performs compilation using the following data sources:
* - %Attachments: the data gathered by the previous passes. See \ref xreate::Attachments.
* - Transcend solutions accessible via queries. See \ref xreate::IQuery, \ref xreate::TranscendLayer.
*
* The pass generates a bytecode by employing \ref xreate::LLVMLayer(wrapper over LLVM toolchain).
* Many compilation activities are delegated to more specific routines. Most notable delegated compilation aspects are:
* - Containers support. See \ref xreate::containers.
* - Latex compilation. See \ref xreate::latex.
* - Interpretation support. See \ref xreate::interpretation.
* - Loop saturation support. See \ref xreate::compilation::TransformationsScopeDecorator.
* - External code interaction support. See \ref xreate::ExternLayer (wrapper over Clang library).
*
* \section adaptability_sect Adaptability
* xreate::CompilePass's behaviour can be adapted in several ways:
- * - %Function Decorators to alter function-level compilation. See \ref xreate::compilation::IFunctionUnit
+ * - %Function Decorators to alter function-level compilation. See \ref xreate::compilation::IBruteFunction
* - Code Block Decorators to alter code block level compilation. See \ref xreate::compilation::ICodeScopeUnit.
* Default functionality defined by \ref xreate::compilation::DefaultCodeScopeUnit
* - Targets to allow more versitile extensions.
* Currently only xreate::interpretation::TargetInterpretation use Targets infrastructure. See \ref xreate::compilation::Target.
* - Altering %function invocation. See \ref xreate::compilation::IFnInvocation.
*
* Clients are free to construct a compiler instantiation with the desired decorators by using \ref xreate::compilation::CompilePassCustomDecorators.
* As a handy alias, `CompilePassCustomDecorators<void, void>` constructs the default compiler.
*
*/
diff --git a/cpp/src/pass/compilepass.h b/cpp/src/pass/compilepass.h
index dc4aba2..bc503c1 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,210 +1,225 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* compilepass.h
*/
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include "abstractpass.h"
#include "llvm/IR/Function.h"
namespace xreate {
class TranscendLayer;
class CompilePass;
class LLVMLayer;
namespace interpretation{
class TargetInterpretation;
}
}
namespace xreate { namespace compilation {
-class ICodeScopeUnit;
-class IFunctionUnit;
+class IBruteScope;
+class IBruteFunction;
class TransformationsManager;
/** \brief Holds current position in %AST while traversing*/
struct Context{
- ICodeScopeUnit* scope;
- IFunctionUnit* function;
+ IBruteScope* scope;
+ IBruteFunction* function;
CompilePass* pass;
};
/** \brief Interface for custom function invocation operation compilation
* \details Default implementation is xreate::compilation::BruteFnInvocation
*/
class IFnInvocation {
public:
/** \brief Returns result of custom function invocation for the given arguments*/
virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="") = 0;
};
/** \brief Default IFnInvocation implementation */
class BruteFnInvocation: public IFnInvocation{
public:
BruteFnInvocation(llvm::Function* callee, LLVMLayer* l)
: __callee(callee), __calleeTy(callee->getFunctionType()), llvm(l) {}
BruteFnInvocation(llvm::Value* callee, llvm::FunctionType* ty, LLVMLayer* l)
: __callee(callee), __calleeTy(ty), llvm(l) {}
/** \brief Makes type conversions and returns LLVM call statement with given arguments*/
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="");
protected:
llvm::Value* __callee;
llvm::FunctionType* __calleeTy;
LLVMLayer* llvm;
};
+/** \brief %Function invocation operator decorator to handle latex enabled functions with hidden extra arguments */
+class HiddenArgsFnInvocation : public compilation::IFnInvocation{
+public:
+ HiddenArgsFnInvocation(std::vector<llvm::Value *> args, compilation::IFnInvocation *parent)
+ : __args(args), __parent(parent){}
+
+ llvm::Value *operator()(std::vector<llvm::Value *> &&args, const std::string &hintDecl = "");
+
+private:
+ std::vector<llvm::Value *> __args;
+ compilation::IFnInvocation *__parent;
+};
+
/** \brief Interface to allow modification of CodeScope compilation
* \details Default implementation defined in xreate::compilation::DefaultCodeScopeUnit
*/
-class ICodeScopeUnit{
+class IBruteScope{
public:
- CompilePass* const pass;
- IFunctionUnit* const function;
- const CodeScope* const scope;
- llvm::BasicBlock* currentBlockRaw;
-
- ICodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
- virtual ~ICodeScopeUnit();
+ CompilePass* const pass;
+ IBruteFunction* const function;
+ const CodeScope* const scope;
+ llvm::BasicBlock* currentBlockRaw;
+
+ IBruteScope(const CodeScope* const codeScope, IBruteFunction* f, CompilePass* compilePass);
+ virtual ~IBruteScope();
+
+ virtual llvm::Value* compile(const std::string& hintBlockDecl="")=0;
+ virtual llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="")=0;
+ virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="", const TypeAnnotation& expectedT = TypeAnnotation())=0;
+
+ virtual Symbol bindArg(llvm::Value* value, std::string&& alias)=0;
+ virtual void bindArg(llvm::Value* value, const ScopedSymbol& s)=0;
+ virtual void reset() = 0;
- virtual llvm::Value* compile(const std::string& hintBlockDecl="")=0;
- virtual llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="")=0;
- virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="")=0;
-
- virtual Symbol bindArg(llvm::Value* value, std::string&& alias)=0;
- virtual void bindArg(llvm::Value* value, const ScopedSymbol& s)=0;
- virtual void reset() = 0;
protected:
-
- /** \brief For subclasses to implement this method to define a function name resolution*/
- virtual IFnInvocation* findFunction(const Expression& opCall)=0;
+ /** \brief For subclasses to implement this method to define a function name resolution*/
+ virtual IFnInvocation* findFunction(const Expression& opCall)=0;
};
-/** \brief Minimal useful ICodeScopeUnit implementation suited for inheritance */
-class BasicCodeScopeUnit: public ICodeScopeUnit{
+/** \brief Minimal useful IBruteScope implementation suited for inheritance */
+class BasicBruteScope: public IBruteScope{
public:
- BasicCodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
+ BasicBruteScope(const CodeScope* const codeScope, IBruteFunction* f, CompilePass* compilePass);
llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="") override;
- llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="") override;
+ llvm::Value* process(const Expression& expr, const std::string& hintAlias="", const TypeAnnotation& expectedT = TypeAnnotation()) override;
llvm::Value* compile(const std::string& hintBlockDecl="") override;
protected:
IFnInvocation* findFunction(const Expression& opCall) override;
+
+private:
+ std::string getIndexStr(const Expression& index);
};
/** \brief Interface to specify compilation of %Function */
-class IFunctionUnit{
+class IBruteFunction{
public:
- IFunctionUnit(ManagedFnPtr f, CompilePass* p): function(f), pass(p) {}
- virtual ~IFunctionUnit();
+ IBruteFunction(ManagedFnPtr f, CompilePass* p): function(f), pass(p) {}
+ virtual ~IBruteFunction();
llvm::Function* compile();
- ICodeScopeUnit* getEntry();
- ICodeScopeUnit* getScopeUnit(const CodeScope * const scope);
- ICodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
+ IBruteScope* getEntry();
+ IBruteScope* getScopeUnit(const CodeScope * const scope);
+ IBruteScope* getScopeUnit(ManagedScpPtr scope);
virtual llvm::Type* prepareResult() = 0;
ManagedFnPtr function;
llvm::Function* raw = nullptr;
protected:
CompilePass* pass=nullptr;
virtual std::string prepareName() = 0;
virtual std::vector<llvm::Type*> prepareSignature() = 0;
virtual llvm::Function::arg_iterator prepareBindings() = 0;
private:
- std::map<const CodeScope * const, std::weak_ptr<ICodeScopeUnit>> __scopes;
- std::list<std::shared_ptr<ICodeScopeUnit>> __orphanedScopes;
+ std::map<const CodeScope * const, std::weak_ptr<IBruteScope>> __scopes;
+ std::list<std::shared_ptr<IBruteScope>> __orphanedScopes;
};
-/** \brief Minimal useful IFunctionUnit implementation suited for inheritance */
-class BasicFunctionUnit: public IFunctionUnit{
+/** \brief Minimal useful IBruteFunction implementation suited for inheritance */
+class BasicBruteFunction: public IBruteFunction{
public:
- BasicFunctionUnit(ManagedFnPtr f, CompilePass* p)
- : IFunctionUnit(f, p) {}
+ BasicBruteFunction(ManagedFnPtr f, CompilePass* p)
+ : IBruteFunction(f, p) {}
protected:
std::string prepareName() override;
virtual std::vector<llvm::Type*> prepareSignature() override;
virtual llvm::Type* prepareResult() override;
virtual llvm::Function::arg_iterator prepareBindings() override;
};
} // end of namespace compilation
class CompilePass : public AbstractPass<void> {
- friend class compilation::BasicCodeScopeUnit;
- friend class compilation::IFunctionUnit;
+ friend class compilation::BasicBruteScope;
+ friend class compilation::IBruteFunction;
public:
compilation::TransformationsManager* managerTransformations;
interpretation::TargetInterpretation* targetInterpretation;
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
/** \brief Executes compilation process */
void run() override;
/**\brief Returns compiled specified %Function
* \details Executes function compilation or read cache if it's already done
*/
- compilation::IFunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
+ compilation::IBruteFunction* getFunctionUnit(const ManagedFnPtr& function);
/**\brief Returns compiled main(entry) %Function in program */
llvm::Function* getEntryFunction();
/** \brief Initializes queries required by compiler. See xreate::IQuery, xreate::TranscendLayer */
static void prepareQueries(TranscendLayer* transcend);
-
-
-
+ void prepare();
+
protected:
- virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function)=0;
- virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, compilation::IFunctionUnit* function)=0;
+ virtual compilation::IBruteFunction* buildFunctionUnit(const ManagedFnPtr& function)=0;
+ virtual compilation::IBruteScope* buildCodeScopeUnit(const CodeScope* const scope, compilation::IBruteFunction* function)=0;
private:
//TODO free `functions` in destructor
- std::map<unsigned int, compilation::IFunctionUnit*> functions;
+ std::map<unsigned int, compilation::IBruteFunction*> functions;
llvm::Function* entry = 0;
};
namespace compilation{
/** \brief Constructs compiler with desired %Function and %Code Scope decorators. See adaptability in xreate::CompilePass*/
template<class FUNCTION_DECORATOR=void, class SCOPE_DECORATOR=void>
class CompilePassCustomDecorators: public ::xreate::CompilePass{
public:
CompilePassCustomDecorators(PassManager* manager): ::xreate::CompilePass(manager) {}
- virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function) override{
+ virtual compilation::IBruteFunction* buildFunctionUnit(const ManagedFnPtr& function) override{
return new FUNCTION_DECORATOR(function, this);
}
- virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function) override{
+ virtual compilation::IBruteScope* buildCodeScopeUnit(const CodeScope* const scope, IBruteFunction* function) override{
return new SCOPE_DECORATOR(scope, function, this);
}
};
template<>
-compilation::IFunctionUnit*
+compilation::IBruteFunction*
CompilePassCustomDecorators<void, void>::buildFunctionUnit(const ManagedFnPtr& function);
template<>
-compilation::ICodeScopeUnit*
-CompilePassCustomDecorators<void, void>::buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function);
+compilation::IBruteScope*
+CompilePassCustomDecorators<void, void>::buildCodeScopeUnit(const CodeScope* const scope, IBruteFunction* function);
}} //end of namespace xreate::compilation
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
index e4adedc..d4da4b1 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,266 +1,266 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* dfapass.cpp
*/
/**
* \file dfapass.h
* \brief Data Flow Analysis
*/
//DEBT DFA represent VersionaPass in declarative form using applyDependencies
// applyDependencies(expression, context, cache, decl);
//DEBT DFA prepare static annotations and represent InterpretationPass in declarative form
// applyStaticAnnotations(expression, context, cache, decl);
//DEBT DFA Eliminate dfa schemes
#include "pass/dfapass.h"
#include "xreatemanager.h"
#include "transcendlayer.h"
#include <boost/format.hpp>
#include <boost/variant/variant.hpp>
using namespace std;
namespace xreate {namespace dfa {
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, graph{new DFAGraph()}
, transcend(manager->transcend) { }
void
DFAPass::processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result) {
const string &nameCalleeFunction=expr.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction=man->root->getFunctionSpecializations(nameCalleeFunction);
vector<SymbolNode> operands;
operands.reserve(expr.getOperands().size());
for(const Expression& arg : expr.getOperands()) {
operands.push_back(process(arg, context));
}
//Set calling relations:
DFACallInstanceType type=variantsCalleeFunction.size()>1?WEAK:STRONG;
for(ManagedFnPtr function : variantsCalleeFunction) {
CodeScope *scopeRemote=function->getEntryScope();
DFACallInstance callInstance;
callInstance.fnName=function->getName();
callInstance.type=type;
std::vector<SymbolNode>::const_iterator nodeActual=operands.begin();
for(const std::string &identFormal : scopeRemote->__bindings) {
const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), versions::VERSION_NONE};
SymbolPacked symbolFormalPacked=transcend->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction+":"+identFormal);
callInstance.args.push_back(std::make_pair(symbolFormalPacked, *nodeActual));
++nodeActual;
}
callInstance.retActual=result;
SymbolNode retFormal=SymbolNode(transcend->pack(Symbol{ScopedSymbol::RetSymbol, scopeRemote}, nameCalleeFunction+":[ret]"));
graph->addCallInstance(std::move(callInstance));
}
}
void
DFAPass::processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache) {
cache.operands.reserve(expression.getOperands().size());
for(const Expression &op : expression.getOperands()) {
const SymbolNode& subnodeOperand=process(op, context);
cache.operands.push_back(subnodeOperand);
graph->addDependency(node, subnodeOperand);
}
cache.blocks.reserve(expression.blocks.size());
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context);
cache.blocks.push_back(subnodeBlock);
graph->addDependency(node, subnodeBlock);
}
}
void
DFAPass::processAnnotations(const Expression& expression, PassContext context, const SymbolNode& ident){
for (const pair<std::string, Expression>& tag : expression.tags){
graph->printInplaceAnnotation(ident, tag.second);
}
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl) {
SymbolNode result;
- if(Attachments::exists<SymbolAlias>(expression)){
- Symbol varSymbol=Attachments::get<SymbolAlias>(expression);
+ if(Attachments::exists<ExprAlias_A>(expression)){
+ Symbol varSymbol=Attachments::get<ExprAlias_A>(expression);
result=transcend->pack(varSymbol, varDecl);
} else if(expression.__state==Expression::IDENT&&expression.tags.size()==0){
Symbol varSymbol=Attachments::get<IdentifierSymbol>(expression);
result=transcend->pack(varSymbol, expression.getValueString());
} else {
result=SymbolAnonymous{expression.id};
}
processAnnotations(expression, context, result);
ProcessingCache cache;
switch(expression.__state) {
case Expression::COMPOUND: {
switch(expression.op) {
case Operator::CALL: {
processCallInstance(expression, context, result);
break;
}
case Operator::IF: {
const SymbolNode& scopeA=process(expression.blocks.front(), context, "ifTrue" + std::to_string(expression.id));
const SymbolNode& scopeB=process(expression.blocks.back(), context, "ifFalse" + std::to_string(expression.id));
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, scopeA);
graph->addDependency(result, scopeB);
graph->addDependency(result, condition);
graph->printWeakAlias(result, scopeA);
graph->printWeakAlias(result, scopeB);
break;
}
case Operator::SWITCH:
case Operator::SWITCH_VARIANT: {
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context, "case"+to_string(block->getBody().id));
graph->addDependency(result, subnodeBlock);
graph->printWeakAlias(result, subnodeBlock);
}
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, condition);
break;
}
case Operator::MAP:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::MAP, {result, cache.operands.at(0), cache.blocks.at(0)});
break;
case Operator::FOLD:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::FOLD, {result, cache.operands.at(0), cache.operands.at(1), cache.blocks.at(0)});
break;
case Operator::LIST:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::LIST, {result}, expression.getOperands().size());
break;
case Operator::LIST_RANGE:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::LIST_RANGE, {result});
break;
case Operator::INDEX:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::INDEX, {result, cache.operands.at(0), cache.operands.at(1)});
break;
default: {
processDependencies(result, expression, context, cache);
break;
}
}
break;
}
case Expression::IDENT: {
SymbolNode symbIdent=AbstractPass<SymbolNode>::process(expression, context, varDecl);
if(!(result==symbIdent)){
graph->addDependency(result, symbIdent);
graph->printAlias(result, symbIdent);
}
break;
}
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::INVALID:
case Expression::BINDING: {
assert(false);
break;
}
}
return result;
}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) {
if (!hintBlockDecl.empty()) {
Symbol symbRet{ScopedSymbol::RetSymbol, scope};
transcend->pack(symbRet, hintBlockDecl + ":[ret]");
}
for(const std::string& binding : scope->__bindings) {
Symbol bindingSymb{scope->getSymbol(binding), scope};
SymbolPacked bindingSymbP=transcend->pack(bindingSymb, binding);
getSymbolCache().setCachedValue(bindingSymb, SymbolNode(bindingSymbP));
processAnnotations(scope->getDefinition(bindingSymb), context, SymbolNode(bindingSymbP));
}
return AbstractPass<SymbolNode>::process(scope, context, hintBlockDecl);
}
SymbolNode
DFAPass::process(ManagedFnPtr function) {
transcend->pack(Symbol{ScopedSymbol::RetSymbol, function->getEntryScope()}, function->getName()+to_string(function.id())+":[ret]");
SymbolNode result=AbstractPass<SymbolNode>::process(function);
graph->printFunctionRet(function, result);
return result;
}
void
DFAPass::finish() {
transcend->registerReport(graph);
//Declare symbols:
graph->printSymbols(transcend);
AbstractPass::finish();
}
} //end of namespace dfa
template<>
SymbolNode
defaultValue() {
assert(false);
}
} //end of xreate namespace
/**
* \class xreate::dfa::DFAPass
* \details Provides DFA, an important analysis for the reasoning. Traverses over AST and stores the collected data in the \ref xreate::dfa::DFAGraph
*/
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index e4b1265..5f1d29e 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,554 +1,563 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: interpretationpass.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 5, 2016, 5:21 PM
*/
/**
* \file interpretationpass.h
* \brief Interpretation analysis: determines what parts of a code could be interpreted
*/
+#include "ast.h"
#include "pass/interpretationpass.h"
-#include <compilation/targetinterpretation.h>
+#include "compilation/targetinterpretation.h"
+#include "analysis/utils.h"
+#include "analysis/predefinedanns.h"
+
#include <bits/stl_vector.h>
-#include "ast.h"
+
//DEBT implement InterpretationPass purely in transcend
//DEBT represent InterpretationPass as general type inference
using namespace std;
namespace xreate {
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>() {
return interpretation::CMPL_ONLY;
}
namespace interpretation {
enum InterpretationQuery {
QUERY_INTR_ONLY, QUERY_CMPL_ONLY
};
namespace details {
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(InterpretationResolution flag) {
return( (flag==INTR_ONLY&&FLAG_REQUIRED==QUERY_INTR_ONLY)
||(flag==CMPL_ONLY&&FLAG_REQUIRED==QUERY_CMPL_ONLY));
}
InterpretationResolution
recognizeTags(const map<std::string, Expression>& tags) {
- auto i=tags.find("i12n");
- if(i==tags.end()){
- return ANY;
- }
-
- assert(i->second.op==Operator::CALL);
- const string& cmd=i->second.operands.at(0).getValueString();
-
- //TODO make consistent names of annotation and resolution
- if(cmd=="on"){
- return INTR_ONLY;
-
- } else if(cmd=="off"){
- return CMPL_ONLY;
- }
-
- return ANY;
+ std::list<Expression> tagsL;
+ auto predefined = analysis::PredefinedAnns::instance();
+ for(const auto& tag: tags){tagsL.push_back(tag.second);}
+ const Expression& tagI12nE = analysis::findAnnById(
+ (unsigned) analysis::PredefinedAnns::ExprAnnotations::I12N,
+ ExpandedType(predefined.exprAnnsT),
+ tagsL);
+
+ if (!tagI12nE.isValid()) return ANY;
+ analysis::PredefinedAnns::I12ModeTag modeI12n = (analysis::PredefinedAnns::I12ModeTag) tagI12nE.operands.at(0).getValueDouble();
+
+ switch(modeI12n){
+ case analysis::PredefinedAnns::I12ModeTag::ON:
+ return INTR_ONLY;
+ case analysis::PredefinedAnns::I12ModeTag::OFF:
+ return CMPL_ONLY;
+ }
+
+ return ANY;
}
}
InterpretationResolution
unify(InterpretationResolution flag) {
return flag;
}
template<typename FLAG_A, typename FLAG_B, typename... FLAGS>
InterpretationResolution
unify(FLAG_A flagA, FLAG_B flagB, FLAGS... flags) {
if(flagA==ANY){
return unify(flagB, flags...);
}
if(flagB==ANY){
return unify(flagA, flags...);
}
assert(flagA==flagB);
return flagA;
}
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
return details::checkConstraints<FLAG_REQUIRED>(flag);
}
template<InterpretationQuery FLAG_REQUIRED_A, InterpretationQuery FLAG_REQUIRED_B, InterpretationQuery... FLAGS>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
flags.pop_back();
if(details::checkConstraints<FLAG_REQUIRED_A>(flag)){
return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
}
return false;
}
bool
InterpretationData::isDefault() const {
return(resolution==ANY&&op==NONE);
}
void
recognizeTags(const Expression& e) {
InterpretationData tag{details::recognizeTags(e.tags), NONE};
if(!tag.isDefault())
Attachments::put<InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f) {
return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
: AbstractPass(manager) {
- Attachments::init<FunctionInterpretationData>();
+ Attachments::init<I12nFunctionSpec>();
Attachments::init<InterpretationData>();
}
void
InterpretationPass::run() {
ManagedFnPtr f=man->root->begin<Function>();
auto& visitedSymbols=getSymbolCache();
while(f.isValid()) {
const Symbol&symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
if(!visitedSymbols.isCached(symbolFunction)){
visitedSymbols.setCachedValue(symbolFunction, process(f));
}
++f;
}
}
InterpretationResolution
InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl) {
recognizeTags(expression);
InterpretationResolution resolution=ANY;
InterpretationOperator opNo=NONE;
switch(expression.__state) {
case Expression::NUMBER:
case Expression::STRING:
{
break;
}
case Expression::IDENT:
{
resolution=Parent::processSymbol(Attachments::get<IdentifierSymbol>(expression), context);
break;
}
case Expression::COMPOUND:
break;
default:
{
resolution=CMPL_ONLY;
break;
}
}
if(expression.__state==Expression::COMPOUND)
switch(expression.op) {
case Operator::EQU:
case Operator::NE:
{
InterpretationResolution left=process(expression.operands[0], context);
InterpretationResolution right=process(expression.operands[1], context);
resolution=unify(left, right);
break;
}
case Operator::LOGIC_AND:
{
assert(expression.operands.size()==1);
resolution=process(expression.operands[0], context);
break;
}
case Operator::CALL:
{
size_t sizeOperands = expression.operands.size();
std::vector<InterpretationResolution> operands;
operands.reserve(sizeOperands);
for(size_t opNo=0; opNo<sizeOperands; ++opNo) {
const Expression &operand=expression.operands[opNo];
operands.push_back(process(operand, context));
}
//TODO cope with static/dynamic context
//TODO BUG here: if several variants they all are processed as CMPL regardless of signature
- list<ManagedFnPtr> callees=man->root->getFunctionSpecializations(expression.getValueString());
+ list<ManagedFnPtr> callees=man->root->getFnSpecializations(expression.getValueString());
if(callees.size()!=1){
resolution=CMPL_ONLY;
break;
}
ManagedFnPtr callee=callees.front();
const Symbol& symbCalleeFunc{ScopedSymbol::RetSymbol, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, context.function->getEntryScope()};
if(!(symbSelfFunc==symbCalleeFunc)){
InterpretationResolution resCallee=processFnCall(callee, context);
assert(resCallee!=FUNC_POSTPONED&&"Indirect recursion detected: can't decide on interpretation resolution");
resolution=unify(resolution, resCallee);
}
//check arguments compatibility
- const FunctionInterpretationData& calleeSignature=FunctionInterpretationHelper::getSignature(callee);
+ const I12nFunctionSpec& calleeSignature=FunctionInterpretationHelper::getSignature(callee);
for(size_t opNo=0; opNo<sizeOperands; ++opNo){
InterpretationResolution argActual=operands.at(opNo);
InterpretationResolution argExpected=calleeSignature.signature[opNo];
//TODO use args unification result to properly process function call
unify(argActual, argExpected);
}
if(FunctionInterpretationHelper::needPartialInterpretation(callee)){
opNo=CALL_INTERPRET_PARTIAL;
}
break;
}
case Operator::CALL_INTRINSIC:
{
- resolution=CMPL_ONLY;
- break;
+ switch((IntrinsicFn) expression.getValueDouble()){
+ case IntrinsicFn::REC_FIELDS: resolution = INTR_ONLY; break;
+ default: resolution=CMPL_ONLY; break;
+ }
+ break;
}
case Operator::QUERY:
{
resolution=INTR_ONLY;
break;
}
case Operator::QUERY_LATE:
{
InterpretationResolution predicate=process(expression.operands[0], context);
unify(predicate, INTR_ONLY);
CodeScope* exprBody=expression.blocks.front();
const std::string& argName=expression.bindings[0];
Symbol argS = {
ScopedSymbol{exprBody->__identifiers.at(argName), versions::VERSION_NONE},
exprBody
};
getSymbolCache().setCachedValue(argS, INTR_ONLY);
Parent::process(expression.blocks.front(), context);
resolution = CMPL_ONLY;
opNo=QUERY_LATE;
break;
}
case Operator::SWITCH_LATE:
{
resolution = CMPL_ONLY;
opNo = SWITCH_LATE;
break;
}
case Operator::IF:
{
InterpretationResolution flagCondition=process(expression.getOperands()[0], context);
InterpretationResolution flagScope1=Parent::process(expression.blocks.front(), context);
InterpretationResolution flagScope2=Parent::process(expression.blocks.back(), context);
//special case: IF_INTERPRET_CONDITION
if(checkConstraints<QUERY_INTR_ONLY>({flagCondition})){
opNo=IF_INTERPRET_CONDITION;
flagCondition=ANY;
}
resolution=unify(flagCondition, flagScope1, flagScope2);
break;
}
case Operator::FOLD:
{
InterpretationResolution flagInput=process(expression.getOperands()[0], context);
InterpretationResolution flagAccumInit=process(expression.getOperands()[1], context);
CodeScope* scopeBody=expression.blocks.front();
const std::string& nameEl=expression.bindings[0];
Symbol symbEl{ScopedSymbol
{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbEl, InterpretationResolution(flagInput));
const std::string& nameAccum=expression.bindings[1];
Symbol symbAccum{ScopedSymbol
{scopeBody->__identifiers.at(nameAccum), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbAccum, InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody=Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if(checkConstraints<QUERY_INTR_ONLY>({flagInput})){
opNo=FOLD_INTERPRET_INPUT;
flagInput=ANY;
}
resolution=unify(flagInput, flagAccumInit, flagBody);
break;
}
case Operator::INDEX:
{
for(const Expression &opNo : expression.getOperands()) {
resolution=unify(resolution, process(opNo, context));
}
break;
}
case Operator::SWITCH:
{
InterpretationResolution flagCondition=process(expression.operands[0], context);
bool hasDefaultCase=expression.operands[1].op==Operator::CASE_DEFAULT;
//determine conditions resolution
InterpretationResolution flagHeaders=flagCondition;
for(size_t size=expression.operands.size(), i=hasDefaultCase?2:1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
flagHeaders=unify(flagHeaders, Parent::process(exprCase.blocks.front(), context));
}
if(checkConstraints<QUERY_INTR_ONLY>({flagHeaders})){
opNo=SWITCH_INTERPRET_CONDITION;
flagHeaders=ANY;
}
//determine body resolutions
resolution=flagHeaders;
for(size_t size=expression.operands.size(), i=1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
resolution=unify(resolution, Parent::process(exprCase.blocks.back(), context));
}
break;
}
case Operator::SWITCH_VARIANT:
{
InterpretationResolution resolutionCondition=process(expression.operands.at(0), context);
resolution=resolutionCondition;
if(checkConstraints<QUERY_INTR_ONLY>({resolution})){
opNo=SWITCH_VARIANT;
resolution=ANY;
}
const string identCondition=expression.bindings.front();
for(auto scope : expression.blocks) {
//set binding resolution
ScopedSymbol symbolInternal=scope->getSymbol(identCondition);
getSymbolCache().setCachedValue(Symbol{symbolInternal, scope}, InterpretationResolution(resolutionCondition));
resolution=unify(resolution, Parent::process(scope, context));
}
for(auto scope : expression.blocks) {
resolution=unify(resolution, Parent::process(scope, context));
}
break;
}
case Operator::LIST:
{
for(const Expression &opNo : expression.getOperands()) {
resolution=unify(resolution, process(opNo, context));
}
break;
}
case Operator::VARIANT:
{
if(expression.getOperands().size()){
resolution=process(expression.getOperands().front(), context);
} else {
resolution=ANY;
}
break;
}
default:
{
resolution=CMPL_ONLY;
for(const Expression &opNo : expression.getOperands()) {
process(opNo, context);
}
for(CodeScope* scope : expression.blocks) {
Parent::process(scope, context);
}
break;
}
}
InterpretationData dataExpected=
Attachments::get<InterpretationData>(expression,{ANY, NONE});
resolution=unify(resolution, dataExpected.resolution);
if(resolution!=dataExpected.resolution || opNo != dataExpected.op ){
Attachments::put<InterpretationData>(expression,{resolution, opNo});
}
return resolution;
}
InterpretationResolution
InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context) {
return process(function);
}
InterpretationResolution
InterpretationPass::process(ManagedFnPtr function) {
CodeScope* entry=function->getEntryScope();
std::vector<std::string> arguments=entry->__bindings;
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& cache=getSymbolCache();
if(cache.isCached(symbSelfFunc))
return cache.getCachedValue(symbSelfFunc);
- const FunctionInterpretationData& fnSignature=FunctionInterpretationHelper::getSignature(function);
+ const I12nFunctionSpec& fnSignature=FunctionInterpretationHelper::getSignature(function);
InterpretationResolution fnResolutionExpected=details::recognizeTags(function->getTags());
//mark preliminary function resolution as expected
if(fnResolutionExpected!=ANY){
cache.setCachedValue(symbSelfFunc, move(fnResolutionExpected));
} else {
// - in order to recognize indirect recursion mark this function resolution as POSTPONED
cache.setCachedValue(symbSelfFunc, FUNC_POSTPONED);
}
//set resolution for function arguments as expected
for(int argNo=0, size=arguments.size(); argNo<size; ++argNo) {
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(arguments[argNo]), versions::VERSION_NONE}, entry};
cache.setCachedValue(symbArg, InterpretationResolution(fnSignature.signature[argNo]));
}
PassContext context;
context.function=function;
context.scope=entry;
InterpretationResolution resActual=process(CodeScope::getDefinition(symbSelfFunc), context);
resActual=unify(resActual, fnResolutionExpected);
return cache.setCachedValue(symbSelfFunc, move(resActual));
}
-const FunctionInterpretationData
+const I12nFunctionSpec
FunctionInterpretationHelper::getSignature(ManagedFnPtr function) {
- if(Attachments::exists<FunctionInterpretationData>(function)){
- return Attachments::get<FunctionInterpretationData>(function);
+ if(Attachments::exists<I12nFunctionSpec>(function)){
+ return Attachments::get<I12nFunctionSpec>(function);
}
- FunctionInterpretationData&& data=recognizeSignature(function);
- Attachments::put<FunctionInterpretationData>(function, data);
+ I12nFunctionSpec&& data=recognizeSignature(function);
+ Attachments::put<I12nFunctionSpec>(function, data);
return data;
}
-FunctionInterpretationData
+I12nFunctionSpec
FunctionInterpretationHelper::recognizeSignature(ManagedFnPtr function) {
CodeScope* entry=function->__entry;
- FunctionInterpretationData result;
+ I12nFunctionSpec result;
result.signature.reserve(entry->__bindings.size());
bool flagPartialInterpretation=false;
for(size_t no=0, size=entry->__bindings.size(); no<size; ++no) {
const std::string& argName=entry->__bindings[no];
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(argName), versions::VERSION_NONE}, entry};
const Expression& arg=CodeScope::getDefinition(symbArg);
InterpretationResolution argResolution=details::recognizeTags(arg.tags);
flagPartialInterpretation|=(argResolution==INTR_ONLY);
result.signature.push_back(argResolution);
}
result.flagPartialInterpretation=flagPartialInterpretation;
return result;
}
bool
FunctionInterpretationHelper::needPartialInterpretation(ManagedFnPtr function) {
- const FunctionInterpretationData& data=getSignature(function);
+ const I12nFunctionSpec& data=getSignature(function);
return data.flagPartialInterpretation;
}
}
} //end of namespace xreate::interpretation
/** \class xreate::interpretation::InterpretationPass
*
* The class encapsulates *Interpretation Analysis* to support [Interpretation](/d/concepts/interpretation/).
*
* It recognizes program functions, expressions, instructions eligible for interpretation
- * and stores the output in \ref Attachments<FunctionInterpretationData> and \ref Attachments<InterpretationData>
+ * and stores the output in \ref Attachments<I12nFunctionSpec> and \ref Attachments<InterpretationData>
*
* There are number of instructions currently eligible for interpretation:
* - Basic literals: numbers and strings
* - Compounds: lists, structs, variants
* - Non-versioned identifiers
* - Comparison and logic operators
* - %Function calls
* - `query` intrinsic function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
* Some of these instructions are eligible also for *late interpretation* to allow coupling
* of compiled instructions with interpreted ones, those are:
* - Partial function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
* \sa xreate::interpretation::TargetInterpretation, [Interpretation Concept](/d/concepts/interpretation/)
*/
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
index 22702bf..88a76f3 100644
--- a/cpp/src/pass/interpretationpass.h
+++ b/cpp/src/pass/interpretationpass.h
@@ -1,96 +1,96 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: interpretationpass.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 5, 2016, 5:21 PM
*/
#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H
#include "abstractpass.h"
#include <map>
#ifndef FRIENDS_INTERPRETATION_TESTS
#define FRIENDS_INTERPRETATION_TESTS
#endif
//TODO refactor interpretation. Get rid of InterpretationOperator, put only one operator - Hybrid/Late.
namespace xreate{ namespace interpretation{
enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
enum InterpretationOperator{
NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, QUERY_LATE,
SWITCH_INTERPRET_CONDITION, SWITCH_VARIANT, SWITCH_LATE,
CALL_INTERPRET_PARTIAL
};
struct InterpretationData{
InterpretationResolution resolution;
InterpretationOperator op;
bool isDefault() const;
};
- struct FunctionInterpretationData{
+ struct I12nFunctionSpec{
typedef std::vector<InterpretationResolution> Signature;
Signature signature;
bool flagPartialInterpretation;
};
class FunctionInterpretationHelper {
public:
- static const FunctionInterpretationData
+ static const I12nFunctionSpec
getSignature(ManagedFnPtr function);
static bool needPartialInterpretation(ManagedFnPtr function);
private:
- static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
+ static I12nFunctionSpec recognizeSignature(ManagedFnPtr function);
};
/** \brief Provides the interpretation analysis. Determines parts of a program eligible for Interpretation by \ref xreate::interpretation::TargetInterpretation */
class InterpretationPass: public AbstractPass<InterpretationResolution> {
typedef AbstractPass<InterpretationResolution> Parent;
public:
InterpretationResolution process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
InterpretationResolution process(ManagedFnPtr function);
InterpretationResolution processFnCall(ManagedFnPtr function, PassContext context);
InterpretationPass(PassManager* manager);
void run();
};
namespace details {
InterpretationResolution recognizeTags(const std::map<std::string, Expression>& tags);
}
} //end of namespace interpretation
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>();
template<>
-struct AttachmentsDict<interpretation::FunctionInterpretationData>
+struct AttachmentsDict<interpretation::I12nFunctionSpec>
{
- typedef interpretation::FunctionInterpretationData Data;
+ typedef interpretation::I12nFunctionSpec Data;
static const unsigned int key = 5;
};
template<>
struct AttachmentsDict<interpretation::InterpretationData>
{
typedef interpretation::InterpretationData Data;
static const unsigned int key = 3;
};
} //end of namespace xreate
#endif /* INTERPRETATIONPASS_H */
diff --git a/cpp/src/pass/ipass.h b/cpp/src/pass/ipass.h
new file mode 100644
index 0000000..442a765
--- /dev/null
+++ b/cpp/src/pass/ipass.h
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on: Jan, 2020
+*/
+
+#ifndef XREATE_IPASS_H
+#define XREATE_IPASS_H
+
+namespace xreate{
+class PassManager;
+
+/** \brief Interface for all passes to inherit. \ref xreate::PassManager holds a collection of passes to execute */
+class IPass{
+public:
+ IPass(PassManager *manager);
+
+ virtual ~IPass(){}
+
+ /** \brief Executes pass */
+ virtual void run() = 0;
+
+ /** \brief Finalizes pass. Empty by default*/
+ virtual void finish();
+
+ PassManager *man;
+};
+}
+
+#endif //XREATE_IPASS_H
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 9bfa1a5..2b8fc8c 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,111 +1,112 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* containers.cpp
* Created on 3/14/15.
*/
#include <transcendlayer.h>
#include "query/containers.h"
+#include "analysis/resources.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
if (Attachments::exists<Implementation>(s)) {
return Attachments::get<Implementation>(s);
}
return Implementation::create(s);
}
Query::Query() {
Attachments::init<Implementation>();
}
void
Query::init(TranscendLayer* transcend) {
if (flagDataIsLoaded) return;
//Fill implementation data for a data sources:
- auto range = transcend->query(Config::get("containers.id.implementations"));
+ auto range = transcend->query(xreate::analysis::CONTAINERS_ID_IMPL_PREDICATE);
if (range.size())
for(auto atom : range) {
auto data = TranscendLayer::parse<SymbolPacked, Gringo::Symbol>(atom.second);
Symbol var = transcend->unpack(get<0>(data));
string implStr = get<1>(data).name().c_str();
- if (implStr == Config::get("containers.impl.solid")) {
+ if (implStr == xreate::analysis::CONTAINERS_IMPL_SOLID_PREDICATE) {
auto size = TranscendLayer::parse<int>(get<1>(data));
Attachments::put<Implementation>(var,{SOLID, ImplementationRec<SOLID>
{get<0>(size)}});
- } else if (implStr == Config::get("containers.impl.onthefly")) {
+ } else if (implStr == xreate::analysis::CONTAINERS_IMPL_ONTHEFLY_PREDICATE) {
Attachments::put<Implementation>(var,{ON_THE_FLY, ImplementationRec<ON_THE_FLY>
{var}});
} else {
assert(false && "Unable to determine proper implementation for the symbol");
}
}
flagDataIsLoaded = true;
}
Implementation
Implementation::create(const Symbol &var) {
//TODO review implementation determination strategy
Expression varDecl = CodeScope::getDefinition(var);
switch (varDecl.op) {
case Operator::LIST_RANGE:
{
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST:
{
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
default: break;
};
ImplementationLinkedList ill(var);
if (ill) {
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
return Implementation();
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source) {
const Expression& sourceExpr = CodeScope::getDefinition(source);
- if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))) {
+ if (sourceExpr.tags.count(analysis::CONTAINERS_ID_LINKLIST_PREDICATE)) {
flagIsValid = true;
- Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
+ Expression tagLinkedlist = sourceExpr.tags.at(analysis::CONTAINERS_ID_LINKLIST_PREDICATE);
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 7765645..8f19dd9 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,96 +1,96 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* containers.h
* Created on 3/14/15.
*/
/**
* \file query/containers.h
* \brief Transcend solutions on [Containers](/d/concepts/containers/) implementation details
*/
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "xreatemanager.h"
#include "transcendlayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
/**
* \brief Queries Transcend solutions on containers implementation details
- * \sa xreate::containers::Iterator
+ * \sa xreate::containers::IFwdIteratorIR
*/
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(TranscendLayer* transcend);
Query();
~Query(){}
private:
bool flagDataIsLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/query/demand.cpp b/cpp/src/query/demand.cpp
new file mode 100644
index 0000000..a2c791d
--- /dev/null
+++ b/cpp/src/query/demand.cpp
@@ -0,0 +1,45 @@
+//
+// Created by pgess on 25/01/2020.
+//
+
+#include "query/demand.h"
+#include "analysis/resources.h"
+using namespace xreate::demand;
+using namespace std;
+void
+DemandQuery::init(TranscendLayer* transcend){
+ const StaticModel& modelF = transcend->query(analysis::DEMAND_FORMAL_PREDICATE);
+ for (const auto& entry: modelF){
+ std::string fn, arg, typeAlias;
+ tie(fn, arg, typeAlias) = TranscendLayer::parse(schemeT<analysis::DEMAND_FORMAL_SCHEME>{}, entry.second);
+ __demand[fn].emplace(arg, typeAlias);
+ }
+
+ const StaticModel& modelA = transcend->query(analysis::DEMAND_ACTUAL_PREDICATE);
+ for (const auto& entry: modelA){
+ ASTSitePacked site;
+ std::string arg;
+ Gringo::Symbol value;
+ tie(site, arg, value) = TranscendLayer::parse(schemeT<analysis::DEMAND_ACTUAL_SCHEME>{}, entry.second);
+
+ __supply[transcend->unpack(site)].emplace(arg, value);
+ }
+}
+
+Demand
+DemandQuery::getFnDemand(const std::string& fn){
+ if(__demand.count(fn))
+ return __demand.at(fn);
+
+ return Demand();
+}
+
+Supply
+DemandQuery::getFnSupply(const ASTSite& siteCall){
+ if(__supply.count(siteCall))
+ return __supply.at(siteCall);
+
+ return Supply();
+}
+
+
diff --git a/cpp/src/query/demand.h b/cpp/src/query/demand.h
new file mode 100644
index 0000000..959bf2b
--- /dev/null
+++ b/cpp/src/query/demand.h
@@ -0,0 +1,30 @@
+//
+// Created by pgess on 19/01/2020.
+//
+
+#ifndef XREATE_DEMAND_H
+#define XREATE_DEMAND_H
+
+#include "transcendlayer.h"
+
+namespace xreate{ namespace demand{
+
+typedef std::map<std::string, std::string> Demand; //key->type
+typedef std::map<std::string, Gringo::Symbol> Supply;
+
+class DemandQuery: public IQuery{
+public:
+ Demand getFnDemand(const std::string& fn);
+ Supply getFnSupply(const ASTSite& siteCall);
+
+public:
+ void init(TranscendLayer* transcend) override;
+
+private:
+ std::map<std::string, Demand> __demand;
+ std::map<ASTSite, Supply> __supply;
+};
+
+}} //end of namespace xreate::demand
+
+#endif //XREATE_DEMAND_H
diff --git a/cpp/src/query/latex.cpp b/cpp/src/query/latex.cpp
index 6970cc7..c20dac8 100644
--- a/cpp/src/query/latex.cpp
+++ b/cpp/src/query/latex.cpp
@@ -1,101 +1,101 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 25, 2018, 12:14 PM
*
* \file latex.cpp
* \brief latex
*/
#include "query/latex.h"
#include "aux/transcend-decorators.h"
using namespace std;
using namespace xreate::latereasoning;
namespace xreate{
namespace latex{
void
LatexQuery::init(TranscendLayer* transcend) {
__transcend = transcend;
//schema: latex_fn_demand(Fn, Subject)
StaticModel data = __transcend->query("latex_fn_demand_ordered");
for(const auto& entry : data) {
string fnName, subject; size_t id;
tie(fnName, subject, id) = __transcend->parse<string, string, int>(entry.second);
__demand[fnName].resize(std::max(__demand[fnName].size(), id+1));
__demand[fnName][id] = subject;
}
//schema: latex_registered_subjects(Subject, Decision)
data = __transcend->query("latex_registered_subjects");
for(const auto& entry : data) {
string subject;
Gringo::Symbol decision;
tie(subject, decision) = __transcend->parse<string, Gringo::Symbol>(entry.second);
__domains[subject].push_back(decision);
}
//schema: latex_decision(Scope, Subject, Decision)
data = __transcend->query("latex_decision");
for(const auto& entry : data) {
ScopePacked scope;
string subject;
Gringo::Symbol decision;
tie(scope, subject, decision) = __transcend->parse<ScopePacked, string, Gringo::Symbol>(entry.second);
- __decisions[make_pair(scope, subject)] = entry.second;
+ __valuesStatic[make_pair(scope, subject)] = entry.second;
}
//schema: latex_parameters_offset(int)
//Override parameter from transcend
data = __transcend->query("latex_parameters_offset");
if(data.size()) {
LatexParametersOffset = std::get<0>(__transcend->parse<unsigned int>(data.begin()->second));
}
auto transcendLate =
Decorators<LateReasoningTranscendDecoratorTag>::getInterface(__transcend);
//Later decisions. schema: Scope, Subject, Decision
LateAnnotationsGroup group = transcendLate->queryLate("latex_decision");
for (auto entry: group.annotations) {
auto key = __transcend->parse<ScopePacked, string>(entry.first);
- __decisionsLate.emplace(make_pair(get<0>(key), get<1>(key)), entry.second);
+ __valuesLate.emplace(make_pair(get<0>(key), get<1>(key)), entry.second);
}
}
Demand
LatexQuery::getFnDemand(const std::string& fnName) {
if (!__demand.count(fnName)) return Demand();
return __demand.at(fnName);
}
latereasoning::LateAnnotation
-LatexQuery::getDecision(const std::string& subject, const CodeScope* scopeCaller) {
- ScopePacked scopeP = __transcend->pack(scopeCaller);
+LatexQuery::getValue(const std::string& key, const CodeScope* context) {
+ ScopePacked scopeP = __transcend->pack(context);
- if(__decisions.count(make_pair(scopeP, subject))){
+ if(__valuesStatic.count(make_pair(scopeP, key))){
//found static decision
- return LateAnnotation(__decisions.at(make_pair(scopeP, subject)));
+ return LateAnnotation(__valuesStatic.at(make_pair(scopeP, key)));
}
- return __decisionsLate.at(make_pair(scopeP, subject));
+ return __valuesLate.at(make_pair(scopeP, key));
}
std::list<Gringo::Symbol>
-LatexQuery::getSubjectDomain(const std::string& subject) {
- assert(__domains.count(subject));
- return __domains.at(subject);
+LatexQuery::getDomain(const std::string& key) {
+ assert(__domains.count(key));
+ return __domains.at(key);
}
}
}
diff --git a/cpp/src/query/latex.h b/cpp/src/query/latex.h
index c66f39f..e842936 100644
--- a/cpp/src/query/latex.h
+++ b/cpp/src/query/latex.h
@@ -1,45 +1,45 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/**
* \file query/latex.h
* \brief Transcend solution on [Context](/d/concepts/context/) implementation details
*/
#ifndef LATEXQUERY_H
#define LATEXQUERY_H
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <list>
namespace xreate{
namespace latex{
typedef std::vector<std::string> Demand;
/** \brief Queries Transcend solution on [Context](/d/concepts/context/) implementation details */
class LatexQuery: public IQuery{
public:
VNameId LatexParametersOffset = 1000; //Default value. Overriden by `latex_parameters_offset` from transcend
Demand getFnDemand(const std::string& fnName);
- latereasoning::LateAnnotation getDecision(const std::string& subject, const CodeScope* scopeCaller);
- std::list<Gringo::Symbol> getSubjectDomain(const std::string& subject);
+ latereasoning::LateAnnotation getValue(const std::string& key, const CodeScope* context);
+ std::list<Gringo::Symbol> getDomain(const std::string& key);
void init(TranscendLayer* transcend);
private:
TranscendLayer* __transcend;
std::map<std::string, Demand> __demand;
- std::map<std::pair<ScopePacked, std::string>, Gringo::Symbol> __decisions;
- std::map<std::pair<ScopePacked, std::string>, latereasoning::LateAnnotation> __decisionsLate;
+ std::map<std::pair<ScopePacked, std::string>, Gringo::Symbol> __valuesStatic;
+ std::map<std::pair<ScopePacked, std::string>, latereasoning::LateAnnotation> __valuesLate;
std::map<std::string, std::list<Gringo::Symbol>> __domains;
};
}
}
#endif
diff --git a/cpp/src/query/polymorph.cpp b/cpp/src/query/polymorph.cpp
index 52f6aa0..7a4b3fd 100644
--- a/cpp/src/query/polymorph.cpp
+++ b/cpp/src/query/polymorph.cpp
@@ -1,71 +1,43 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: polymorph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
#include "polymorph.h"
#include "aux/transcend-decorators.h"
+#include "analysis/resources.h"
+
using namespace std;
+using namespace xreate::analysis;
namespace xreate{
namespace polymorph{
-const std::string atomPolymorph = "dfa_callguard";
-
void
-PolymorphQuery::init(TranscendLayer* transcend) {
- __transcend = transcend;
-
- StaticModel queryResult = transcend->query(atomPolymorph);
- if (queryResult.size()) {
- for (auto entry : queryResult) {
- auto answer = TranscendLayer::parse<SymbolNode, Gringo::Symbol>(entry.second);
- SymbolNode symbCaller = std::get<0>(answer);
- SymbolGeneralized symbCallerUnpacked = transcend->unpack(symbCaller);
-
- __cacheEarlyReasoning.emplace(symbCallerUnpacked, entry.second);
- }
- }
-
- auto transcendLate =
- Decorators<LateReasoningTranscendDecoratorTag>::getInterface(__transcend);
- latereasoning::LateAnnotationsGroup group = transcendLate->queryLate(atomPolymorph);
-
- for(auto entry : group.annotations) {
- auto targetWrapper = Gringo::Symbol::createTuple(Gringo::SymSpan{&entry.first, 1});
- auto targetSP = __transcend->parse<SymbolNode>(targetWrapper);
- SymbolGeneralized targetS = __transcend->unpack(std::get<0>(targetSP));
- __cacheLateReasoning.emplace(targetS, entry.second);
- }
-}
-
-latereasoning::LateAnnotation
-PolymorphQuery::get(const Expression& e) const {
- SymbolGeneralized targetS = Attachments::exists<SymbolAlias>(e) ?
- SymbolGeneralized(Attachments::get<SymbolAlias>(e))
- : SymbolGeneralized(SymbolAnonymous{e.id});
-
- if (__cacheEarlyReasoning.count(targetS)) {
- return latereasoning::LateAnnotation(__cacheEarlyReasoning.at(targetS));
- }
-
- if (__cacheLateReasoning.count(targetS)) {
- return __cacheLateReasoning.at(targetS);
+PolymorphQuery::init(TranscendLayer *transcend){
+ StaticModel model = transcend->query(POLYMORPH_SUPPLY_PREDICATE);
+ if(model.size()){
+ for(const auto& entry : model){
+ ASTSitePacked sitePacked; Gringo::Symbol value; string schemeStr;
+ tie(sitePacked, value, schemeStr) = TranscendLayer::parse(schemeT<POLYMORPH_SUPPLY_SCHEME>{}, entry.second);
+ TypeAnnotation schemeRaw(TypeOperator::ALIAS, {});
+ schemeRaw.__valueCustom = schemeStr;
+ ExpandedType scheme = transcend->ast->expandType(schemeRaw);
+ __modelEarlyReasoning.emplace(
+ transcend->unpack(sitePacked),
+ make_pair(value, scheme)
+ );
}
-
- assert(false && "Can't find a guard");
-}
-
-Expression
-PolymorphQuery::getValue(const Gringo::Symbol& symbol) const {
- auto result = __transcend->parse<Gringo::Symbol, Expression>(symbol);
- return std::get<1>(result);
+ }
}
+std::pair<Gringo::Symbol, ExpandedType>
+PolymorphQuery::getFnSupply(const ASTSite& siteCall){
+ return __modelEarlyReasoning.at(siteCall);
}
-} //end of xreate::polymorph
+}} //end of xreate::polymorph
diff --git a/cpp/src/query/polymorph.h b/cpp/src/query/polymorph.h
index 7be4f56..79d8c46 100644
--- a/cpp/src/query/polymorph.h
+++ b/cpp/src/query/polymorph.h
@@ -1,42 +1,41 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: polymorph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
/**
* \file query/polymorph.h
* \brief Transcend solution on [Polymorphism](/d/concepts/polymorphism/) implementation details
*/
#ifndef POLYMORPHQUERY_H
#define POLYMORPHQUERY_H
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <unordered_map>
namespace xreate { namespace polymorph {
/** \brief Queries Transcend solution on [Polymorphism](/d/concepts/polymorphism/) implementation details */
class PolymorphQuery: public IQuery {
public:
- latereasoning::LateAnnotation get(const Expression& e) const;
- Expression getValue(const Gringo::Symbol& s) const;
- virtual void init(TranscendLayer* transcend) override;
-
+ std::pair<Gringo::Symbol, ExpandedType> getFnSupply(const ASTSite& siteCall);
+
+public:
+ virtual void init(TranscendLayer* transcend) override;
+
private:
- std::unordered_map<SymbolGeneralized, Gringo::Symbol> __cacheEarlyReasoning;
- std::unordered_map<SymbolGeneralized, latereasoning::LateAnnotation> __cacheLateReasoning;
- TranscendLayer* __transcend = nullptr;
+ std::map<ASTSite, std::pair<Gringo::Symbol, ExpandedType>> __modelEarlyReasoning;
};
}}//end of xreate::polymorph
#endif /* POLYMORPHQUERY_H */
diff --git a/cpp/src/transcendlayer.cpp b/cpp/src/transcendlayer.cpp
index 2ecd979..e158adc 100644
--- a/cpp/src/transcendlayer.cpp
+++ b/cpp/src/transcendlayer.cpp
@@ -1,495 +1,404 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: transcendlayer.cpp
*/
/**
* \file transcendlayer.h
* \brief Transcend reasoning implementation
*/
#include "transcendlayer.h"
+#include "analysis/resources.h"
#include "analysis/utils.h"
#include "utils.h"
#include <gringo/scripts.hh>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <memory>
#include <boost/variant/detail/apply_visitor_binary.hpp>
using namespace std;
+using namespace xreate::analysis;
-//TODO escape identifiers started with upper case symbol
+//namespace xreate{
-namespace xreate{
-
-bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2) {
- return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
-}
-
-struct VisitorSymbolNodeHash : public boost::static_visitor<size_t>{
-
- std::size_t operator()(const xreate::SymbolPacked& node) const noexcept {
- return 2 * (node.identifier + 3 * node.scope + 5 * std::abs(node.version));
- }
-
- std::size_t operator()(const xreate::SymbolAnonymous& node) const noexcept {
- return 7 * node.id;
- }
-} ;
-}
-
-namespace std{
-
-std::size_t
-hash<xreate::SymbolNode>::operator()(xreate::SymbolNode const& s) const noexcept {
- return boost::apply_visitor(xreate::VisitorSymbolNodeHash(), s);
-}
-
-std::size_t
-hash<xreate::SymbolGeneralized>::operator()(xreate::SymbolGeneralized const& s) const noexcept {
- return xreate::AttachmentsId<xreate::SymbolGeneralized>::getId(s);
-}
-}
+//bool operator==(const Site& s1, const Site& s2) {
+// return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
+//}
namespace xreate{
void
TranscendLayer::printWarnings(std::ostream& out) {
const std::string warningTag = "warning";
auto warningsModel = query(warningTag);
if(warningsModel.size())
for(auto warning : warningsModel) {
unsigned int warningId;
Gringo::Symbol params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning.second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out << params;
}
}
bool
TranscendLayer::processSolution(Gringo::Model const &model) {
cout << "Model: " << endl;
- const string& atomBindVar = Config::get("transcend.bindings.variable");
- const string& atomBindFunc = Config::get("transcend.bindings.function");
- const string& atomBindScope = Config::get("transcend.bindings.scope");
+ const string& atomBindVar = VAR_ANN_PREDICATE;
+ const string& atomBindFunc = FUNCTION_ANN_PREDICATE;
+ const string& atomBindScope = SCOPE_ANN_PREDICATE;
for(Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
atom.print(cout);
cout << " | " << endl;
string atomName(atom.name().c_str());
if(atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope) {
string atomAlias = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.emplace(atomAlias, atom);
continue;
}
__model.emplace(atomName, atom);
}
return true;
}
void
TranscendLayer::registerReport(IAnalysisReport * report) {
__reports.push_back(report);
}
void
TranscendLayer::printReports() {
for(IAnalysisReport* report : __reports) {
report->print(__partGeneral);
}
}
void
TranscendLayer::deleteReports(){
for(IAnalysisReport* report : __reports) {
delete report;
}
__reports.clear();
}
void
TranscendLayer::addRuleWarning(const RuleWarning & rule) {
- //__partGeneral << rule << endl;
-
- list<string> domains;
- boost::format formatDef("%1%(%2%)");
- std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
- [&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
- string domain;
- switch(argument.second) {
- case DomainAnnotation::FUNCTION:
- domain = "function";
- break;
- case DomainAnnotation::VARIABLE:
- domain = "variable";
- break;
- }
-
- return boost::str(formatDef % domain % argument.first);
- });
-
- list<string> vars;
- std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
- [](const std::pair<std::string, DomainAnnotation> &argument) {
- return argument.first.c_str();
- });
-
- list<list < string>> guardsRaw;
- std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
- [this](const Expression & guard) {
- return xreate::analysis::compile(guard);
- });
-
- const list<string>& guards = xreate::analysis::multiplyLists(std::move(guardsRaw));
- list<string> &&branches = xreate::analysis::compileNeg(rule.__condition);
-
- boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
- for(const string &guardsJoined : guards)
- for(const string &branch : branches) {
- unsigned int hook = registerWarning(string(rule.__message));
-
- __partGeneral << formatWarning
- % (hook)
- % (boost::algorithm::join(vars, ", "))
- % (branch)
- % (guardsJoined)
- % (boost::algorithm::join(domains, ", "))
- << endl;
- }
+ //FIX
}
unsigned int
TranscendLayer::registerWarning(std::string && message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;
}
void
-TranscendLayer::involveImports() {
+TranscendLayer::appendImport() {
ostream &out = __partGeneral;
if(ast)
for(string fn : ast->__rawImports) {
std::ifstream file(fn);
if(!file) {
std::cout << "Can't process script file: " << fn << std::endl;
assert(false);
}
while(!file.eof()) {
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
TranscendLayer::addRawScript(std::string && script) {
__partGeneral << script;
}
void
TranscendLayer::run() {
- involveImports();
+ appendImport();
printReports();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), { }, 0);
ctl.add("base",{}, program.str());
ctl.ground({
{"base",
{}}
}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
this->processSolution(model);
return true;
},
{
});
if(result.satisfiable() == Gringo::SolveResult::Satisfiable) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process solution
for(auto q : __queries) {
q.second->init(this);
}
}
TranscendLayer::TranscendLayer() : ast(nullptr) { }
StaticModel
TranscendLayer::query(const std::string & atom) const {
StaticModel result;
if (! __model.count(atom)) {
return result;
}
auto currentDataRange = __model.equal_range(atom);
std::copy(currentDataRange.first, currentDataRange.second, std::inserter(result, result.end()));
return result;
}
ScopePacked
TranscendLayer::pack(const CodeScope * const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if(pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
size_t
TranscendLayer::getScopesCount() const {
return __registryScopes.size();
}
SymbolPacked
TranscendLayer::pack(const Symbol& symbol, std::string hintSymbolName) {
SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
TranscendLayer::unpack(const SymbolPacked & symbol) const {
return Symbol{ScopedSymbol
{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]};
};
+ASTSitePacked
+TranscendLayer::pack(const ASTSite& s){
+ ASTSitePacked result;
+
+ if(Attachments::exists<ExprAlias_A>(s.id)){
+ Symbol resultS = Attachments::get<ExprAlias_A>(s.id);
+ result = ASTSitePacked(pack(resultS));
+
+ } else{
+ result = ASTSitePacked(s);
+ }
+
+ return result;
+}
+
+ASTSite
+TranscendLayer::unpack(const ASTSitePacked& s){
+ switch(s.tag){
+ case ASTSitePacked::SYMBOL:
+ return {CodeScope::getDefinition(unpack(s.symbol), true).id};
+
+ case ASTSitePacked::ANON:
+ return s.site;
+ }
+ assert(false);
+ return ASTSite();
+}
+
std::string
TranscendLayer::getHintForPackedSymbol(const SymbolPacked & symbol) {
auto result = __indexSymbolNameHints.find(symbol);
return(result == __indexSymbolNameHints.end()) ? "" : result->second;
}
IQuery *
TranscendLayer::registerQuery(IQuery *query, const QueryId & id) {
return __queries.emplace(id, query).first->second;
}
IQuery *
TranscendLayer::getQuery(const QueryId & id) {
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
-class VisitorUnpackSymbol : public boost::static_visitor<SymbolGeneralized>{
-public:
-
- VisitorUnpackSymbol(const TranscendLayer* transcend) : __transcend(transcend) { }
-
- SymbolGeneralized operator()(const SymbolPacked& symbol) const {
- return __transcend->unpack(symbol);
- }
-
- SymbolGeneralized operator()(const SymbolAnonymous& symbol) const {
- return symbol;
- }
-
-private:
- const TranscendLayer* __transcend;
-} ;
-
-class VisitorPackSymbol : public boost::static_visitor<SymbolNode>{
-public:
-
- VisitorPackSymbol(TranscendLayer* transcend, const std::string& hintSymbolName)
- : __transcend(transcend), __hint(hintSymbolName) { }
-
- SymbolNode operator()(const Symbol& symbol) const {
- return __transcend->pack(symbol, __hint);
- }
-
- SymbolNode operator()(const SymbolAnonymous& symbol) const {
- return symbol;
- }
-
-private:
- TranscendLayer* __transcend;
- std::string __hint;
-} ;
-
-SymbolNode
-TranscendLayer::pack(const SymbolGeneralized& symbol, const std::string & hintSymbolName) {
- return boost::apply_visitor(VisitorPackSymbol(this, hintSymbolName), symbol);
-}
-
-SymbolGeneralized
-TranscendLayer::unpack(const SymbolNode & symbol) const {
- return boost::apply_visitor(VisitorUnpackSymbol(this), symbol);
-}
-
bool
operator==(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool
operator<(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
Expression
ParseImplAtom<Expression>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Num: return Expression(atom.num());
case Gringo::SymbolType::Str: return Expression(Atom<String_t>(std::string(atom.string().c_str())));
case Gringo::SymbolType::Fun:
{
//FUNC
Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name().c_str())))});
for(const Gringo::Symbol& arg : atom.args()) {
result.addArg(ParseImplAtom<Expression>::get(arg));
}
return result;
}
default:
{
assert(false);
}
}
}
int
-ParseImplAtom<int>
-::get(const Gringo::Symbol & atom) {
+ParseImplAtom<int>::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Num: return atom.num();
default: break;
}
assert(false && "Inappropriate symbol type");
}
std::string
-ParseImplAtom<std::string>
-::get(const Gringo::Symbol & atom) {
+ParseImplAtom<std::string>::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Str: return atom.string().c_str();
case Gringo::SymbolType::Fun: return atom.name().c_str();
default: break;
}
assert(false && "Inappropriate symbol type");
}
SymbolPacked
-ParseImplAtom<SymbolPacked>
-::get(const Gringo::Symbol & atom) {
+ParseImplAtom<SymbolPacked>::get(const Gringo::Symbol & atom) {
auto result = TranscendLayer::parse<int, int, int>(atom);
return SymbolPacked(std::get<0>(result), std::get<1>(result), std::get<2>(result));
};
Gringo::Symbol
-ParseImplAtom<Gringo::Symbol>
-::get(const Gringo::Symbol & atom) {
+ParseImplAtom<Gringo::Symbol>::get(const Gringo::Symbol & atom) {
return atom;
}
-SymbolNode
-ParseImplAtom<SymbolNode>
-::get(const Gringo::Symbol & atom) {
- assert(atom.type() == Gringo::SymbolType::Fun
- && "Inappropriate symbol type");
+ASTSitePacked
+ParseImplAtom<ASTSitePacked>::get(const Gringo::Symbol & atom) {
+ assert(atom.type() == Gringo::SymbolType::Fun
+ && "Inappropriate symbol type");
- if(atom.name() == "a") {
- return SymbolAnonymous{(unsigned int) std::get<0>(TranscendLayer::parse<int>(atom))};
+ if(atom.name() == SITE_ANON_PREDICATE) {
+ return ASTSitePacked(ASTSite{std::get<0>(TranscendLayer::parse<int>(atom))});
- } else if(atom.name() == "s") {
- return ParseImplAtom<SymbolPacked>::get(atom);
- }
+ } else if(atom.name() == SITE_SYMBOL_PREDICATE) {
+ return ASTSitePacked(ParseImplAtom<SymbolPacked>::get(atom));
+ }
- assert(false && "Wrong symbol format");
+ assert(false && "Wrong symbol format");
}
-class VisitorSymbolId : public boost::static_visitor<unsigned int>{
-public:
+std::string
+ASTSitePacked::str() const {
+ boost::format formatSymbAnonymous(string(SITE_ANON_PREDICATE) + "(%1%)");
+ boost::format formatSymbNamed(string(SITE_SYMBOL_PREDICATE) + "(%1%,%2%,%3%)");
- unsigned int operator()(const Symbol& symbol) const {
- return AttachmentsId<Symbol>::getId(symbol);
+ switch(tag){
+ case ASTSitePacked::SYMBOL:{
+ return boost::str(formatSymbNamed % symbol.identifier % symbol.version % symbol.scope);
}
- unsigned int operator()(const SymbolAnonymous& symbol) const {
- return symbol.id;
+ case ASTSitePacked::ANON:{
+ return boost::str(formatSymbAnonymous % site.id);
}
-} ;
-
-unsigned int
-AttachmentsId<SymbolGeneralized>
-::getId(const SymbolGeneralized & symbol) {
- return boost::apply_visitor(VisitorSymbolId(), symbol);
+ }
}
+//unsigned int
+//AttachmentsId<ASTSite>::getId(const ASTSite& symbol) {
+// return boost::apply_visitor(VisitorSymbolId(), symbol);
+//}
+
} //end of xreate namespace
/**
* \class xreate::TranscendLayer
* \brief Logic reasoning implementation. Internally, it's a proxy to the external ASP solver [Clasp](https://potassco.org/clasp/)
*
* Performs reasoning over source codes in order to facilitate efficient compilation using results from a number of internal analyzers.
* Clients implement \ref IAnalysisReport to supply Transcend with data and implement \ref IQuery to find out resolutions.
*
* Transcend uses the following sources to build a logic program before actual reasoning is performed:
* - Raw content. Clients are free to include arbitrary ASP format data in the logic program. See \ref addRawScript().
- * - External scripts. External files with ASP scripts can be appended to the logic program. See `involveImports()` (private member).
+ * - External scripts. External files with ASP scripts can be appended to the logic program. See `appendImport()` (private member).
* - Diagnostic rules to produce diagnostic messages during
* compilation(warnings) or even to signal to halt compilation with errors. See \ref addRuleWarning(), \ref registerWarning().
* - Internal analyzers. The analyzer can publish logic facts and rules by implementing \ref IAnalysisReport interface.
*
* Generally, Transcend input could be loosely broke down into three categories:
* - Internally derived data. CFA, DFA, and other analyzers automatically supply the reasoner with
* useful insights about source codes, the structure and algorithms of a program.
* - User provided custom data. Analyzers extract manual developer-provided annotations from the source codes.
* - External data. External files supply reasoner with third-party data
* which relates to different aspects of a program possibly produced by external analyzers.
*
* After Transcend has gathered data from all providers and the logic program is fully constructed,
* it runs the external logic reasoner to receive back the solution.
*
* The solution from the external logic reasoner is accessible via *queries*.
* Classes which want to request data from Transcend should implement the \ref IQuery interface. See \ref IQuery descendants to find out currently available queries.
*
* \section tl_adapt Adaptability
* Decorators are used to extend %TranscendLayer functionality. The default bundle defined by \ref DefaultTranscendLayerImpl.
*
* \sa See xreate::dfa::DFAPass, xreate::cfa::CFAPass, xreate::IQuery, xreate::IAnalysisReport
*/
diff --git a/cpp/src/transcendlayer.h b/cpp/src/transcendlayer.h
index 6ad56de..59634cc 100644
--- a/cpp/src/transcendlayer.h
+++ b/cpp/src/transcendlayer.h
@@ -1,284 +1,311 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: transcendlayer.h
*/
#ifndef transcendLAYER_H
#define transcendLAYER_H
#include "ast.h"
#include "contextrule.h"
#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <list>
#include <limits>
namespace xreate {
typedef unsigned int ScopePacked;
const ScopePacked SCOPE_ABSTRACT_GLOBAL = std::numeric_limits<ScopePacked>::max();
struct SymbolPacked {
SymbolPacked(){}
SymbolPacked(ScopedSymbol i, ScopePacked s): identifier(i.id), version(i.version), scope(s){}
SymbolPacked(VNameId symbolId, versions::VariableVersion symbolVersion, ScopePacked symbolScope)
: identifier(symbolId), version(symbolVersion), scope(symbolScope){}
VNameId identifier;
versions::VariableVersion version;
ScopePacked scope;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
-struct SymbolAnonymous {
- unsigned int id;
- bool flagIsUsed = false;
+struct ASTSitePacked {
+ union {
+ ASTSite site;
+ SymbolPacked symbol;
+ };
+ enum { SYMBOL, ANON } tag;
+
+ ASTSitePacked(){}
+ explicit ASTSitePacked(const ASTSite& data): site(data), tag(ASTSitePacked::ANON) {}
+ explicit ASTSitePacked(const SymbolPacked& data): symbol(data), tag(ASTSitePacked::SYMBOL){}
+ std::string str() const;
};
-bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2);
+//bool operator==(const Site& s1, const Site& s2);
-typedef boost::variant<SymbolAnonymous, SymbolPacked> SymbolNode;
-
-//DEBT use SymbolGeneralized communicating with Analysis rather than Symbol
-typedef boost::variant<SymbolAnonymous, Symbol> SymbolGeneralized;
-
-template<>
-struct AttachmentsId<SymbolGeneralized>{
- static unsigned int getId(const SymbolGeneralized& symbol);
-};
+//template<>
+//struct AttachmentsId<Site>{
+// static unsigned int getId(const Site& symbol);
+//};
} namespace std {
- template<>
- struct hash<xreate::SymbolNode> {
- std::size_t operator()(xreate::SymbolNode const& s) const noexcept;
- };
-
- template<>
- struct hash<xreate::SymbolGeneralized> {
- std::size_t operator()(xreate::SymbolGeneralized const& s) const noexcept;
- };
+// template<>
+// struct hash<xreate::SymbolNode> {
+// std::size_t operator()(xreate::SymbolNode const& s) const noexcept;
+// };
+//
+// template<>
+// struct hash<xreate::Site> {
+// std::size_t operator()(xreate::Site const& s) const noexcept;
+// };
}
namespace xreate {
enum class DFGConnection {
STRONG, WEAK, PROTOTYPE
};
/** \brief Supplies \ref TranscendLayer with results of an analysis*/
class IAnalysisReport {
public:
/** \brief Composes a logic program to represent the analysis data in ASP format, and appends to a stream*/
virtual void print(std::ostringstream& output) const = 0;
virtual ~IAnalysisReport(){};
};
/** \brief Transcend solutions querying interface */
class IQuery {
public:
virtual void init(TranscendLayer* transcend) = 0;
virtual ~IQuery() {}
};
enum class QueryId {
ContainersQuery,
PolymorphQuery,
- LatexQuery
+ LatexQuery,
+ DemandQuery
};
namespace dfa{
class DFAGraph;
}
namespace cfa {
class CFAGraph;
}
+template<typename Tuple> struct schemeT{};
typedef std::multimap<std::string, Gringo::Symbol> StaticModel;
typedef StaticModel::const_iterator StaticModelIterator;
class TranscendLayer {
friend class ContextRule;
/**\name Data Providers Management */
///@{
public:
void registerReport(IAnalysisReport* report);
void printReports();
void deleteReports();
/** \brief Appends arbitrary string to a logic program
*/
void addRawScript(std::string&& script);
private:
std::list<IAnalysisReport*> __reports;
/** Includes external text files to a *logic program* */
- void involveImports();
+ void appendImport();
///@}
/**\name Queries Management */
///@{
public:
/** \brief Registers a query. See xreate::IQuery */
IQuery* registerQuery(IQuery* query, const QueryId& id);
/** \brief Returns a particular query. See xreate::IQuery */
IQuery* getQuery(const QueryId& id);
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Symbol& atom);
+
+ template<class ...Types>
+ static std::tuple<Types...> parse(schemeT<std::tuple<Types...>>, const Gringo::Symbol& atom);
+ template<class Ret>
+ static Ret parseAtom(const Gringo::Symbol& atom);
+
StaticModel query(const std::string& atom) const;
size_t getScopesCount() const;
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
ScopePacked pack(const CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol) const;
- SymbolNode pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName);
- SymbolGeneralized unpack(const SymbolNode& symbol) const;
+// SymbolNode pack(const Site& symbol, const std::string& hintSymbolName);
+// Site unpack(const SymbolNode& symbol) const;
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
+ ASTSitePacked pack(const ASTSite& s);
+ ASTSite unpack(const ASTSitePacked& s);
///@}
private:
std::map<QueryId, IQuery*> __queries;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<const CodeScope*> __registryScopes;
/**\name Diagnostic */
///@{
//TODO diagnostic move over to separate provider/query
public:
/** \brief Registers diagnostic rules */
void addRuleWarning(const RuleWarning &rule);
/** \brief Registers diagnostic messages */
unsigned int registerWarning(std::string &&message);
private:
std::map<unsigned int, std::string> __warnings;
void printWarnings(std::ostream& out);
///@}
///@{
public:
TranscendLayer();
/** \brief Executes reasoning */
void run();
///@}
AST *ast;
protected:
virtual bool processSolution(Gringo::Model const &model);
private:
StaticModel __model;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<int> {
static int get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Symbol& atom);
};
template<>
-struct ParseImplAtom<SymbolNode> {
- static SymbolNode get(const Gringo::Symbol& atom);
+struct ParseImplAtom<Gringo::Symbol> {
+ static Gringo::Symbol get(const Gringo::Symbol& atom);
};
template<>
-struct ParseImplAtom<Gringo::Symbol> {
- static Gringo::Symbol get(const Gringo::Symbol& atom);
+struct ParseImplAtom<ASTSitePacked> {
+ static ASTSitePacked get(const Gringo::Symbol& atom);
};
template<class ItemType>
struct ParseImplAtom<std::list<ItemType>>{
static std::list<ItemType>
get(const Gringo::Symbol& atom){
bool flagIsList = (atom.type() == Gringo::SymbolType::Fun) && atom.name().empty();
std::list<ItemType> result;
if(!flagIsList) {
//treat as degenerate case: list with a single element
result.push_back(ParseImplAtom<ItemType>::get(atom));
return result;
}
for (const Gringo::Symbol& arg: atom.args()) {
result.push_back(ParseImplAtom<ItemType>::get(arg));
}
return result;
}
};
template<>
struct ParseImplAtom<Expression> {
static Expression get(const Gringo::Symbol& atom);
};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType;
ElType& el = std::get < tupleSize - index > (tup);
Gringo::Symbol atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index - 1 > ::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0> {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
}
};
template<class ...Types>
std::tuple<Types...>
TranscendLayer::parse(const Gringo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
+
+template<class ...Types>
+std::tuple<Types...>
+TranscendLayer::parse(schemeT<std::tuple<Types...>>, const Gringo::Symbol& atom){
+ return parse<Types...>(atom);
+}
+
+template<class Ret>
+Ret
+TranscendLayer::parseAtom(const Gringo::Symbol& atom){
+ return ParseImplAtom<Ret>::get(atom);
+}
+
+
} //end of xreate namespace
#endif
diff --git a/cpp/src/utils.cpp b/cpp/src/utils.cpp
index a901e38..7f55338 100644
--- a/cpp/src/utils.cpp
+++ b/cpp/src/utils.cpp
@@ -1,38 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* utils.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file cpp/src/utils.h
* \brief Auxiliary code
*/
#include "utils.h"
#include <boost/locale/encoding_utf.hpp>
using namespace xreate;
-Config Config::__self = Config();
-
-Config::Config()
-: __storage{json_file{ "config/default.json" }}
-{}
-
using boost::locale::conv::utf_to_utf;
std::wstring
utf8_to_wstring(const std::string& str)
{
- return utf_to_utf<wchar_t>(str.c_str(), str.c_str() + str.size());
+ return utf_to_utf<wchar_t>(str.c_str(), str.c_str() + str.size());
}
std::string
wstring_to_utf8(const std::wstring& str)
{
return utf_to_utf<char>(str.c_str(), str.c_str() + str.size());
}
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index 626ec4a..cd4ae1a 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,172 +1,160 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* utils.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef UTILS_H
#define UTILS_H
-#include "jeayeson/jeayeson.hpp"
+#include <vector>
+#include <string>
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>();
- }
-};
-
/** \brief Decorators support */
template<class DecoratorTag>
struct DecoratorsDict{
//typedef ConcreteDecoratorForTag result;
};
template<class DecoratorTag>
struct Decorators{
typedef typename DecoratorsDict<DecoratorTag>::result Instance;
template<class Base>
static Instance* getInterface(Base* obj){
Instance* result = dynamic_cast< Instance* > (obj);
assert(result);
return result;
}
};
template<class Target>
struct ManagedPtr {
static ManagedPtr<Target> Invalid() {
return ManagedPtr<Target>();
}
ManagedPtr() : __storage(0) {
}
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);
}
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();
}
ManagedPtr<Target>& operator++() {
++__id;
return *this;
}
inline unsigned int id() const {
return __id;
}
bool operator< (const ManagedPtr<Target>& other) const{
if(__storage != other.__storage) return __storage < other.__storage;
return __id < other.__id;
}
private:
unsigned int __id = 0;
const std::vector<Target*> * __storage = 0;
};
}
std::wstring
utf8_to_wstring(const std::string& str);
std::string
wstring_to_utf8(const std::wstring& str);
#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/src/xreatemanager.cpp b/cpp/src/xreatemanager.cpp
index 974bdc4..cfc526d 100644
--- a/cpp/src/xreatemanager.cpp
+++ b/cpp/src/xreatemanager.cpp
@@ -1,151 +1,152 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
#include "xreatemanager.h"
-#include "pass/abstractpass.h"
+#include "pass/ipass.h"
#include "aux/transcend-decorators.h"
#include "aux/xreatemanager-decorators.h"
#include "llvmlayer.h"
+
#include <assert.h>
#include <list>
namespace xreate {
void
PassManager::registerPass(IPass* pass, const PassId& id, IPass* parent)
{
__passes.emplace(id, pass);
__passDependencies.emplace(parent, pass);
}
IPass*
PassManager::getPassById(const PassId& id){
assert(__passes.count(id));
return __passes[id];
}
bool
PassManager::isPassRegistered(const PassId& id){
return __passes.count(id);
}
void
PassManager::executePasses(){
std::list<IPass*> passes{nullptr};
while (passes.size()){
IPass* parent = passes.front();
auto range = __passDependencies.equal_range(parent);
for (auto i=range.first; i!=range.second; ++i){
IPass* pass = i->second;
pass->run();
pass->finish();
passes.push_back(pass);
}
passes.pop_front();
}
}
void
PassManager::prepare(AST* ast){
root = ast;
transcend = new DefaultTranscendLayerImpl();
transcend->ast = ast;
llvm = new LLVMLayer(ast);
}
PassManager::~PassManager(){}
typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault;
namespace details{ namespace tier2{
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
namespace details { namespace tier1 {
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
XreateManager*
XreateManager::prepare(std::string&& code) {
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}
/**
* \class xreate::XreateManager
* \brief Entry point of Xreate API
*
* Manages whole Xreate compiler's internal workflow. There are 4 distinctive stages managed by XreateManager:
* - `initPasses()` To init passes.
* - `executePasses()` To execute passes.
* - `analyse()` To run the reasoner.
* - `run()` To run the compiler.
*
* * \section xm_adapt Adaptability
* For adaptability reasons XreateManager comes with several *frontends*:
* - `xreate::details::tier2::XreateManager` exposes all the stages to clients for full control.
* - `xreate::details::tier1::XreateManager` exposes `analyse()` along with `run()`, where `analyse()` combines execution of all previous stages.
* - `xreate::XreateManager` exposes `run()` only which properly initializes and executes all the stages for convenient use.
*
* Besides, there are also *backends* as follows:
* - \ref XreateManagerDecoratorBase Simple backend intended for inheritance, does not provide much functionality.
* - \ref XreateManagerDecoratorFull Backend intended to initialize all builtin passes.
*
* Thus, client could combine a desired frontend along with a desired backend as it sees fit.
* Default xreate::XreateManager wraps around the full backend to init all builtin passes, and
* the simplest frontend with the only `run()` exposed to execute all stages at once.
*/
\ No newline at end of file
diff --git a/cpp/src/xreatemanager.h b/cpp/src/xreatemanager.h
index 1d2f8ad..4289e79 100644
--- a/cpp/src/xreatemanager.h
+++ b/cpp/src/xreatemanager.h
@@ -1,145 +1,146 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.h
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
/**
* \file
* \brief The entry point of Xreate API.
*/
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include <string>
#include <map>
//stdio external
struct _IO_FILE;
typedef struct _IO_FILE FILE;
namespace xreate { namespace grammar { namespace main {
class Scanner;
}}}
namespace xreate {
class IPass;
class TranscendLayer;
class LLVMLayer;
class AST;
enum class PassId {
CFAPass, CFATemporalSeqPass,
CompilePass,
DFAPass,
EnvironmentTestsPass,
LoggerPass,
RulesPass,
- InterpretationPass,
- VersionsPass
+ InterpretationPass,
+ VersionsPass,
+ TranscendPass
};
/**
* \class PassManager
* \brief The base class to control passes
*/
class PassManager{
public:
void prepare(AST* ast);
void registerPass(IPass* pass, const PassId& id, IPass* prerequisite=nullptr);
IPass* getPassById(const PassId& id);
bool isPassRegistered(const PassId& id);
void executePasses();
virtual ~PassManager();
TranscendLayer* transcend;
LLVMLayer* llvm;
AST* root;
private:
std::map<PassId, IPass*> __passes;
std::multimap<IPass*, IPass*> __passDependencies;
};
namespace details{ namespace tier2{
class XreateManager: public virtual PassManager{
public:
virtual ~XreateManager(){};
virtual void initPasses()=0;
// virtual void executePasses()=0;
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public Decorator {
public:
};
}} //namespace details::tier2
namespace details{ namespace tier1{
class XreateManager: public virtual PassManager{
public:
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier2::XreateManagerImpl<Decorator> {
typedef details::tier2::XreateManagerImpl<Decorator> PARENT;
public:
void analyse(){
PARENT::initPasses();
PARENT::executePasses();
PARENT::analyse();
}
void* run(){
return PARENT::run();
}
};
}} //namespace details::tier1
class XreateManager: public virtual PassManager{
public:
/** \brief Consequently executes all compilation and code execution phases */
virtual void* run()=0;
/** \brief Constructs XreateManager for a given code */
static XreateManager* prepare(std::string&& code);
/** \brief Constructs XreateManager for a given script file */
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier1::XreateManagerImpl<Decorator>{
typedef details::tier1::XreateManagerImpl<Decorator> PARENT;
public:
void* run(){
PARENT::analyse();
return PARENT::run();
}
};
} //namespace xreate
#endif
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 188831b..4272d95 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,61 +1,26 @@
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>)
-
+INCLUDE_DIRECTORIES("${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/")
# TESTS
#=========================
FIND_PACKAGE (LLVM REQUIRED)
message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set (LIBCLASP_PATH ${CLINGO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
#aux_source_directory(. TEST_FILES)
-set(TEST_FILES
- universal.cpp
- introduction.cpp
- unit-test-example.cpp
- transcend-ast.cpp
- supplemental/docutils
- latetranscend.cpp
- cfa.cpp
- latex.cpp
- polymorph.cpp
- transcend.cpp
- virtualization.cpp
- exploitation.cpp
- effects-communication.cpp
- association.cpp
- main.cpp
- modules.cpp
- attachments.cpp
- ast.cpp
- dfa.cpp
- compilation.cpp
- ExpressionSerializer.cpp
- externc.cpp
- types.cpp
- #vendorsAPI/clangAPI.cpp
- #vendorsAPI/xml2.cpp
- #vendorsAPI/json.cpp
-
- containers.cpp
- interpretation.cpp
- loops.cpp
-
- #supplemental/versions-algorithm-data_dependency.cpp
- effects-versions.cpp
-)
-add_executable(${PROJECT_NAME} ${TEST_FILES})
+add_executable(${PROJECT_NAME} ${XREATE_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/association.cpp b/cpp/tests/association.cpp
index df36c38..9370a64 100644
--- a/cpp/tests/association.cpp
+++ b/cpp/tests/association.cpp
@@ -1,138 +1,139 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* association.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on August 12, 2017, 9:28 PM
*/
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "pass/interpretationpass.h"
#include "supplemental/docutils.h"
#include <gtest/gtest.h>
using namespace xreate::interpretation;
using namespace xreate;
using namespace std;
TEST(Association, TypedQuery_1) {
auto man = ::xreate::details::tier1::XreateManager::prepare(R"Code(
- AtomNumT = type slave atomNumT.
- AtomStrT = type slave atomStrT.
- CompListT = type slave compListT.
- CompArithT = type slave compArithT.
+ AtomNumT = type slave("atomNumT").
+ AtomStrT = type slave("atomStrT").
+ CompListT = type slave("compListT").
+ CompArithT = type slave("compArithT").
- test = function:: num; entry
+ test = function:: int; entry()
{
query1 = intrinsic query("atomNumT")::[AtomNumT].
query2 = intrinsic query("atomStrT")::[AtomStrT].
query3 = intrinsic query("compListT")::[CompListT].
query4 = intrinsic query("compArithT")::[CompArithT].
test1 = query1[0] == 5:: bool.
test2 = query2[1] == "y":: bool.
test3 = query3[0, 1] == "x" :: bool.
test4 = query4[0, 0, 0] == 1:: bool.
test1 + test2 + test3 + test4
}
)Code");
man->transcend->addRawScript(R"RAW(
atomNumT(5; 8).
atomStrT("x"; "y").
compListT(5, "x").
compListT(8, "y").
compArithT(add(1, 2)).
compArithT(mul(5, 6)).
)RAW");
man->analyse();
int (*test)() = (int (*)())man->run();
int result = test();
ASSERT_EQ(4, result);
}
TEST(Association, QueryLate_ast_1){
auto man = XreateManager::prepare(
R"Code(
- test = function:: num; entry
+ test = function:: int; entry()
{
intrinsic query late("dict"->x:: bool)::bool
{
(x == true)
}
}
)Code");
}
TEST(Association, QueryLate_pass_1){
auto man = ::xreate::details::tier1::XreateManager::prepare(
R"Code(
- test = function:: num; entry
+ test = function:: int; entry()
{
intrinsic query late("dict"->x:: bool)::bool
{
(x == true)
}
}
)Code");
man->analyse();
Expression instructionE = man->root->findFunction("test")->getEntryScope()->getBody();
InterpretationData instructionData = Attachments::get<InterpretationData>(instructionE);
ASSERT_EQ(QUERY_LATE, instructionData.op);
}
TEST(Association, QueryLate_target_1){
auto man = ::xreate::details::tier1::XreateManager::prepare(
R"Code(
Equipment = type variant {dresser, sink, stove}.
Room = type variant{kitchen, bedroom, bathroom}.
- test = function:: num; entry
+ test = function:: int; entry
{
room = bedroom() :: Room; room.
equipment = intrinsic query late("whatshere"->x:: Equipment)::int; equipment
{ if (x == dresser()):: int {1} else {0} }.
equipment + (room::int)
}
)Code");
man->transcend->addRawScript(
R"RAW(
room(kitchen; bedroom; bathroom).
equipment(dresser;sink;stove).
interior(kitchen, stove).
interior(bedroom, dresser).
interior(bathroom, sink).
late(VarTarget, VarRoom, Room, whatshere(Equipment)):-
bind(VarTarget, equipment);
bind(VarRoom, room);
interior(Room, Equipment);
equipment(Equipment);
room(Room).
)RAW");
man->analyse();
int (*result)() = (int (*)()) man->run();
ASSERT_EQ(2, result());
}
TEST(Association, Doc_IntrinsicQuery_2){
string scriptGUI = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "IntrinsicQuery_2_GUI");
string scriptPlatform = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "IntrinsicQuery_2_Platform");
string scriptRules = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "IntrinsicQuery_2_Rules");
string code = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "IntrinsicQuery_2_Code");
-
+
+ std::cout << code << std::endl;
auto man = xreate::details::tier1::XreateManager::prepare(move(code));
man->transcend->addRawScript(move(scriptGUI));
man->transcend->addRawScript(move(scriptPlatform));
man->transcend->addRawScript(move(scriptRules));
man->analyse();
delete man;
ASSERT_TRUE(true);
}
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index 15c70c9..2f76ecf 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,264 +1,288 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
-
#include "supplemental/docutils.h"
#include "xreatemanager.h"
#include "main/Parser.h"
-#include "supplemental/defines.h"
+#include "supplemental/basics.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate;
using namespace xreate::grammar::main;
TEST(AST, Containers1) {
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r");
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
fclose(input);
}
TEST(AST, InterfacesDataCFA) {
XreateManager* man = XreateManager::prepare
("interface(cfa){\n"
" operator map :: annotation1.\n"
"}");
auto answer = man->root->__interfacesData.equal_range(CFA);
EXPECT_EQ(1, std::distance(answer.first, answer.second));
Expression&& scheme = move(answer.first->second);
EXPECT_EQ(Operator::MAP, scheme.op);
EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString());
}
TEST(AST, syntax_recognizeIdentifiers) {
XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
a = b:: int.
b = 8:: int.
a
}
)Code");
}
TEST(AST, syntax_operatorIndex) {
XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
b = a[1].
b
}
)Code");
}
TEST(AST, IdentHyphen1){
XreateManager* man = XreateManager::prepare(R"Code(
my-fn = function(m-n:: num):: num; entry
{
b = m-n-1:: int.
b
}
)Code");
}
TEST(AST, Variants_switch) {
XreateManager* man = XreateManager::prepare(R"Code(
Color = type variant{Blue, White, Green}.
main = function:: int {
x = White()::Color.
switch variant(x)::int
case (Green) {0}
case (White) {1}
case (Blue){2}
}
)Code");
Expression e = man->root->findFunction("main")->getEntryScope()->getBody();
ASSERT_EQ(4, e.getOperands().size());
ASSERT_EQ(3, e.blocks.size());
}
+TEST(AST, TypeVariantEmpty){
+ std::string code = R"(
+ my-rec-t = type variant{}
+ )";
+
+ ASSERT_DEATH(XreateManager::prepare(move(code)), "-- line 2 col 29: Variant type can't be empty.");
+}
+
TEST(AST, DISABLED_InterfacesDataDFA) { }
TEST(AST, DISABLED_InterfacesDataExtern) { }
TEST(AST, Doc_LiteralsAndExpressions) {
XreateManager* man = XreateManager::prepare(
R"Code(
Record1 = type {year:: int, month:: string}.
isOdd = function(x :: int) :: bool {true}
test = function:: bool; entry {
x1 = 5 :: int.
x2 = "Nimefurahi kukujua":: string.
x3 = {year = 1934, month = "april"}:: Record1.
x4 = {16, 8, 3} :: [int].
x41 = [1..18]:: [int].
x5 = 8>=3:: bool.
x6 = "Blue" <> "Green" :: bool.
x7 = -true:: bool.
colors = {"Green", "Blue"} :: [string].
color = colors[0] :: string.
date = {year = 1934, month = "april"}:: Record1. year = date["year"] :: int.
a = 0::int. b = 0 :: int.
x7 = a - b:: int.
result = isOdd(6) :: bool.
true
}
)Code");
ASSERT_TRUE(true);
}
TEST(AST, Doc_CodeBlocks1) {
XreateManager* man = XreateManager::prepare(
getDocumentationExampleById("documentation/Syntax/syntax.xml", "CodeBlocks1"));
FnNoArgs resultFn = (FnNoArgs) man->run();
int resultExpected = resultFn();
ASSERT_EQ(12, resultExpected);
}
TEST(AST, Doc_Functions1) {
XreateManager* man = XreateManager::prepare(
getDocumentationExampleById("documentation/Syntax/syntax.xml", "Functions1"));
ASSERT_TRUE(true);
}
TEST(AST, Doc_FunctionSpecializations1) {
XreateManager* man = XreateManager::prepare(
getDocumentationExampleById("documentation/Syntax/syntax.xml", "FunctionSpecialization1"));
ASSERT_TRUE(true);
}
TEST(AST, Doc_BranchStatements) {
string code_IfStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "IfStatement1");
string code_SwitchStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "SwitchStatement1");
string code =
R"Code(
test = function:: int; entry
{
question = "Favorite color?":: string.
monthNum = 2:: int.
%IfStatement1
%SwitchStatement1
monthName
}
)Code";
replace(code, "%IfStatement1", code_IfStatement1);
replace(code, "%SwitchStatement1", code_SwitchStatement1);
XreateManager* man = XreateManager::prepare(move(code));
ASSERT_TRUE(true);
}
TEST(AST, Doc_LoopStatements) {
string code_LoopStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "LoopStatement1");
string code_LoopStatement2 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "LoopStatement2");
string code_FoldStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "FoldStatement1");
string code_MapStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "MapStatement1");
string code =
R"Code(
test = function:: int; entry
{
%LoopStatement1
%LoopStatement2
%FoldStatement1
%MapStatement1
min
}
)Code";
replace(code, "%LoopStatement1", code_LoopStatement1);
replace(code, "%LoopStatement2", code_LoopStatement2);
replace(code, "%FoldStatement1", code_FoldStatement1);
replace(code, "%MapStatement1", code_MapStatement1);
XreateManager::prepare(move(code));
ASSERT_TRUE(true);
}
TEST(AST, Doc_Types){
string code = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Types1");
XreateManager::prepare(move(code));
ASSERT_TRUE(true);
}
TEST(AST, Doc_Variants1){
string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Variants1");
XreateManager::prepare(move(code_Variants1));
ASSERT_TRUE(true);
}
TEST(AST, Doc_VariantsSwitch1){
string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "VariantsSwitch1");
XreateManager::prepare(move(code_Variants1));
ASSERT_TRUE(true);
}
-TEST(AST, Doc_RecField1){
- string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecField1");
- XreateManager::prepare(move(code_Variants1));
-
- ASSERT_TRUE(true);
-}
-
-TEST(AST, Doc_RecUpdate1){
- string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecUpdate1");
- XreateManager::prepare(move(code_Variants1));
-
- ASSERT_TRUE(true);
-}
-
TEST(AST, Doc_Versions1){
string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Versions1_1");
string code_Variants2 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Versions1_2");
string code = R"Code(
test = function:: int; entry
{
<BODY>
y
})Code";
{
+ std::cout << code_Variants1 << std::endl;
XreateManager* man = XreateManager::prepare(move(code_Variants1));
man->run();
delete man;
ASSERT_TRUE(true);
}
- {
- replace(code, "<BODY>", code_Variants2);
- auto man = details::tier1::XreateManager::prepare(move(code));
- ASSERT_DEATH(man->analyse(), ".*versions graph.*");
- }
+// {
+// replace(code, "<BODY>", code_Variants2);
+// auto man = details::tier1::XreateManager::prepare(move(code));
+// ASSERT_DEATH(man->analyse(), ".*versions graph.*");
+// }
+}
+
+TEST(AST, Intrinsics1){
+ string code = R"Code(
+test = function:: [int]
+{
+ intrinsic array_init(8):: [int]
+})Code";
+
+ XreateManager* man = XreateManager::prepare(move(code));
+ const Expression bodyE = man->root->findFunction("test")->getEntryScope()->getBody();
+
+ ASSERT_EQ(Operator::CALL_INTRINSIC, bodyE.op);
+ ASSERT_EQ(IntrinsicFn ::ARR_INIT, (IntrinsicFn) bodyE.getValueDouble());
+}
+
+TEST(AST, TypeRecordEmpty){
+ std::string code = R"(
+ my-rec-t = type {}
+ )";
+
+ ASSERT_DEATH(XreateManager::prepare(move(code)), "-- line 2 col 22: Record type can't be empty.");
+}
+
+TEST(AST, PredPredicates1){
+ string code = R"(
+ my-fn = function:: int; entry() {0}
+ )";
+
+ auto man = XreateManager::prepare(move(code));
}
\ No newline at end of file
diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp
index b15a9e1..1f1bee9 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,193 +1,193 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* cfa.cpp
*
* Created on: Jul 17, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "pass/cfapass.h"
#include "analysis/cfagraph.h"
#include "pass/cfatemporalseqpass.h"
#include "analysis/temporalseqgraph.h"
#include "pass/compilepass.h"
-#include "compilation/scopedecorators.h"
+#include "compilation/decorators.h"
#include "gtest/gtest.h"
#include "aux/xreatemanager-decorators.h"
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <boost/format.hpp>
using namespace xreate;
using namespace xreate::cfa;
using namespace std;
TEST(CFA, testFunctionAnnotations) {
string&& program =
"f2 = function::int; annotationF2 {\n"
" 0\n"
"}\n"
"\n"
"f1 = function:: int; entry; annotationF1 {\n"
" f2() + 10\n"
"}";
details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(program));
man->analyse();
StaticModel answer = man->transcend->query("annotationF1");
EXPECT_EQ(1, answer.size());
answer = man->transcend->query("annotationF2");
EXPECT_EQ(1, answer.size());
}
TEST(CFA, testLoopContextExists) {
details::tier1::XreateManager* man = details::tier1::XreateManager::prepare (
"interface(cfa){\n"
" operator fold:: annotation1.\n"
"}\n"
"\n"
"main = function:: int; entry {\n"
" x = [1..10]:: [int].\n"
" sum = loop fold (x->el:: int, 0->sum):: int {\n"
" el + sum + f1()\n"
" }. \n"
" sum\n"
"}"
"guard:: annotation1 {"
" f1 = function::int {\n"
" x = 0:: int. "
" x\n"
" }"
"}"
);
man->analyse();
StaticModel model = man->transcend->query("annotation1");
ScopePacked scopeIdActual = std::get<0>(TranscendLayer::parse<ScopePacked>(model.begin()->second));
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
const Expression& exprSum = scopeEntry->getDefinition(scopeEntry->getSymbol("sum"));
CodeScope* scopeExpected = exprSum.blocks.front();
ScopePacked scopeIdExpected = man->transcend->pack(scopeExpected);
ASSERT_EQ(scopeIdExpected, scopeIdActual);
}
TEST(CFA, TemporalFnCall) {
details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
R"Code(
a = function::int{
seq
{x = b():: int. x}
{x = 0 :: int. x}::int
}
b = function::int {y = 0. y}
)Code");
CodeScope* scopeSeq1 = man->root->findFunction("a")->getEntryScope()->getBody().blocks.front();
CodeScope* scopeSeq2 = *(++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
CodeScope* scopeB = man->root->findFunction("b")->getEntryScope();
CodeScope* scopeA = man->root->findFunction("a")->getEntryScope();
ScopePacked psSeq1 = man->transcend->pack(scopeSeq1);
ScopePacked psSeq2 = man->transcend->pack(scopeSeq2);
ScopePacked psB = man->transcend->pack(scopeB);
ScopePacked psA = man->transcend->pack(scopeA);
CFATemporalSeqPass* pass = new CFATemporalSeqPass(man);
man->registerPass(pass, PassId::CFATemporalSeqPass);
man->executePasses();
const TemporalSeqGraph* report = dynamic_cast<CFATemporalSeqPass*> (
man->getPassById(PassId::CFATemporalSeqPass))->getReport();
delete pass;
std::ostringstream output;
report->print(output);
cout << output.str() << endl;
ASSERT_TRUE(report->isOrdered(psSeq2, psSeq1));
//ASSERT_TRUE(report->isOrdered(psSeq2, psB));
ASSERT_FALSE(report->isOrdered(psSeq1, psA));
}
TEST(CFA, TemporalChildScope) {
details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
R"Code(
a = function::int{
seq
{x = 0:: int. x}
{x=0::int. if(x>0)::int{1} else {0}}::int
}
)Code");
CodeScope* scopeSeq1 = man->root->findFunction("a")->getEntryScope()->getBody().blocks.front();
CodeScope* scopeSeq2 = *(++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
CodeScope* scopeIf1 = scopeSeq2->getBody().blocks.front();
CodeScope* scopeIf2 = *(++scopeSeq2->getBody().blocks.begin());
ScopePacked psSeq1 = man->transcend->pack(scopeSeq1);
ScopePacked psSeq2 = man->transcend->pack(scopeSeq2);
ScopePacked psIf1 = man->transcend->pack(scopeIf1);
ScopePacked psIf2 = man->transcend->pack(scopeIf2);
CFATemporalSeqPass* pass = new CFATemporalSeqPass(man);
man->registerPass(pass, PassId::CFATemporalSeqPass);
man->executePasses();
const TemporalSeqGraph* report = dynamic_cast<CFATemporalSeqPass*> (
man->getPassById(PassId::CFATemporalSeqPass))->getReport();
delete pass;
std::ostringstream output;
report->print(output);
cout << output.str() << endl;
ASSERT_TRUE(report->isOrdered(psSeq2, psSeq1));
ASSERT_TRUE(report->isOrdered(psIf1, psSeq1));
ASSERT_TRUE(report->isOrdered(psIf2, psSeq1));
ASSERT_FALSE(report->isOrdered(psIf2, psSeq2));
}
TEST(CFA, Temporal_Payload_PathCollapse_1){
details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
R"Code(
import raw("scripts/cfa/payload.lp").
b = function::int {d()}
c = function::int {d()}
d = function::int {0}
a = function:: int {
seq {context:: test. 0} {b() + c()}
}
)Code");
string script =
R"Code(
cfa_payload(P, scope(Scope), ()):-
bind_scope(Scope, P, strong).
)Code";
CFATemporalSeqPass* pass = new CFATemporalSeqPass(man);
man->registerPass(pass, PassId::CFATemporalSeqPass);
man->registerPass(new CFAPass(man), PassId::CFAPass);
man->executePasses();
const TemporalSeqGraph* report = dynamic_cast<CFATemporalSeqPass*> (
man->getPassById(PassId::CFATemporalSeqPass))->getReport();
man->transcend->addRawScript(move(script));
testing::internal::CaptureStdout();
man->analyse();
std::string outputActual = testing::internal::GetCapturedStdout();
cout << outputActual << endl;
string outputExpected = "cfa_payload(test,scope(2),())";
ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
delete pass;
}
\ No newline at end of file
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index f098e2f..d44f2cf 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,243 +1,278 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* compilation.cpp
*
* Created on: -
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
-#include "supplemental/defines.h"
+#include "supplemental/basics.h"
+#include "llvmlayer.h"
#include "gtest/gtest.h"
using namespace xreate;
+using namespace std;
//DEBT implement no pkgconfig ways to link libs
//TOTEST FunctionUnit::compileInline
TEST(Compilation, functionEntry1){
std::unique_ptr<XreateManager> program(XreateManager::prepare(
"func1 = function(a:: int):: int {a+8} \
func2 = function::int; entry {12 + func1(4)} \
"));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = entry();
ASSERT_EQ(24, answer);
}
TEST(Compilation, full_IFStatementWithVariantType){
XreateManager* man = XreateManager::prepare(
"Color = type variant {RED, BLUE, GREEN}.\n"
"\n"
" main = function(x::int):: bool; entry {\n"
" color = if (x == 0 )::Color {RED()} else {BLUE()}.\n"
" if (color == BLUE())::bool {true} else {false}\n"
" }"
);
bool (*main)(int) = (bool (*)(int)) man->run();
ASSERT_FALSE(main(0));
ASSERT_TRUE(main(1));
}
TEST(Compilation, full_Variant1){
XreateManager* man = XreateManager::prepare(R"Code(
- OneArgument = type{x::int}.
- TwoArguments = type{x::int, y::int}.
+ global = type predicate {
+ entry
+ }
Command= type variant{
- Add::TwoArguments,
- Dec::OneArgument
+ Add(x::int, y::int),
+ Dec(x::int)
}.
- main = function::Command; entry {
- Dec({x=2})::Command
+ main = function::Command; entry() {
+ Dec(2) ::Command
}
)Code");
void (*main)() = (void (*)()) man->run();
}
TEST(Compilation, full_SwitchVariant1){
XreateManager* man = XreateManager::prepare(R"Code(
- OneArgument = type{x::int}.
- TwoArguments = type{x::int, y::int}.
-
Command= type variant{
- Add::TwoArguments,
- Dec::OneArgument
+ Add(x::int, y::int),
+ Dec(x::int)
}.
main = function::int; entry {
- //command = Dec({x = 8}):: Command.
- command = Add({x= 3, y= 5}):: Command.
+ command = Add(3, 5):: Command.
switch variant(command)::int
case(Add){command["x"] + command["y"]}
case(Dec){command["x"]}
}
)Code");
int (*mainFn)() = (int (*)()) man->run();
int result = mainFn();
ASSERT_EQ(8, result);
}
TEST(Compilation, full_SwitchVariantNoArguments2){
XreateManager* man = XreateManager::prepare(R"Code(
Command= type variant{Add, Dec}.
main = function::int; entry {
command = Dec():: Command.
switch variant(command)::int
case(Add){0}
case(Dec){1}
}
)Code");
int (*mainFn)() = (int (*)()) man->run();
int result = mainFn();
ASSERT_EQ(1, result);
}
TEST(Compilation, full_SwitchVariantMixedArguments3){
XreateManager* man = XreateManager::prepare(R"Code(
- TwoArguments = type{x::int, y::int}.
Command= type variant{
- Add::TwoArguments,
+ Add(x::int, y::int),
Dec
}.
main = function(arg::int):: int; entry {
- command = if (arg > 0)::Command {Dec()} else {Add({x=1,y=2})}.
+ command = if (arg > 0)::Command {Dec()} else {Add(1, 2)}.
switch variant(command)::int
case(Add){0}
case(Dec){1}
}
)Code");
int (*mainFn)(int) = (int (*)(int)) man->run();
int result = mainFn(5);
ASSERT_EQ(1, result);
}
TEST(Compilation, full_StructUpdate){
XreateManager* man = XreateManager::prepare(
R"Code(
Rec = type {
a :: int,
b:: int
}.
test= function:: int; entry {
a = {a = 18, b = 20}:: Rec.
b = a + {a = 11}:: Rec.
b["a"]
}
)Code");
int (*main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(11, result);
}
TEST(Compilation, AnonymousStruct_init_index){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
x[1]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(15, main());
}
TEST(Compilation, AnonymousStruct_init_update){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
y = x + {6}:: {int, int}.
y[0]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(6, main());
}
TEST(Compilation, BugIncorrectScopes1){
std::string code =
R"Code(
init = function:: int {10}
main = function(cmd:: int):: int; entry {
x = init():: int.
if(cmd > 0):: int { x + 1 } else { x }
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*mainFn)(int) = (int (*)(int)) man->run();
EXPECT_EQ(11, mainFn(1));
}
TEST(Compilation, Sequence1){
std::string code =
R"Code(
interface(extern-c){
libbsd = library:: pkgconfig("libbsd").
include {
libbsd = {"bsd/stdlib.h", "string.h"}
}.
}
start = function:: i32; entry {
seq {
nameNew = "TestingSequence":: string.
setprogname(nameNew)
} {strlen(getprogname())}::i32
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*startFn)() = (int (*)()) man->run();
int nameNewLen = startFn();
ASSERT_EQ(15, nameNewLen);
}
TEST(Compilation, BoolInstructions1){
std::string code =
R"Code(
test = function (a:: bool, b:: bool):: bool; entry
{
-a
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
- Fn2args startFn = (Fn2args) man->run();
+ Fn2Args startFn = (Fn2Args) man->run();
+}
+
+TEST(Compilation, StructIndex1){
+ std::string code =
+ R"Code(
+Anns = type predicate {
+ entry()
+}
+test = function:: int; entry()
+{
+ x = {a = ({b = 3}::{b:: int})}:: {a:: {b:: int}}.
+ 2 + x["a", "b"] + x["a"]["b"]
+}
+)Code";
+
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
+ FnNoArgs startFn = (FnNoArgs) man->run();
+ int result = startFn();
+ ASSERT_EQ(2, result);
+}
+
+TEST(Compilation, PreferredInt1){
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(""));
+ TypesHelper utils(man->llvm);
+ int bitwidth = utils.getPreferredIntTy()->getBitWidth();
+ ASSERT_EQ(64, bitwidth);
+}
+
+TEST(Compilation, PredPredicates1){
+ string code = R"(
+ my-fn = function:: int; entry() {0}
+ )";
+
+ auto man = XreateManager::prepare(move(code));
+ FnNoArgs startFn = (FnNoArgs) man->run();
+ int result = startFn();
+ ASSERT_EQ(0, result);
}
\ No newline at end of file
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 0e7482d..a7123c0 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,155 +1,299 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
#include "query/containers.h"
#include "main/Parser.h"
+
#include "supplemental/docutils.h"
+#include "supplemental/basics.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate::grammar::main;
using namespace xreate::containers;
using namespace xreate;
-typedef int (*IntFn)();
+TEST(Containers, AST_List1){
+ string code = R"(
+ my-test = function:: int {
+ {month = 1, 2, #3 = 8}
+ }
+ )";
-TEST(Containers, ListAsArray){
- XreateManager* man = XreateManager::prepare(
+ auto man = XreateManager::prepare(move(code));
+ const Expression& listE = man->root->findFunction("my-test")->getEntryScope()->getBody();
+ ASSERT_EQ(3, listE.bindings.size());
+ ASSERT_EQ(3, listE.operands.size());
+ set<string> fields;
+ fields.insert(listE.bindings.begin(), listE.bindings.end());
-R"Code(
- main = function(x:: int):: int;entry {
- a = {1, 2, 3}:: [int].
- a[x]
+ ASSERT_TRUE(fields.count("month"));
+ ASSERT_TRUE(fields.count("0"));
+ ASSERT_TRUE(fields.count("3"));
+}
+
+TEST(AST, AST_ListIndex1){
+ string code = R"(
+ my-fn = function:: int; entry()
+ {
+ x = [1..2]:: [int].
+ x + {[1] = 1}
}
-)Code" );
+ )";
+
+ auto man = XreateManager::prepare(move(code));
+ const Expression& bodyE = man->root->findFunction("my-fn")->getEntryScope()->getBody();
+
+ ASSERT_EQ(2, bodyE.operands.size());
+ const Expression opLiInE = bodyE.operands.at(1);
+ ASSERT_EQ(2, opLiInE.operands.size());
+}
+
+TEST(Containers, DONE_RecInitByList1){
+string code = R"(
+ Rec = type {x:: int, y:: int}.
+ test = function(a:: int, b::int):: Rec; entry() {
+ {x = a + b, y = 2}
+ }
+)";
+
+ auto man = XreateManager::prepare(move(code));
+ man->run();
+}
+
+TEST(Containers, DONE_RecInitByList2){
+ string code = R"(
+ Rec = type {x:: int, y:: int}.
+ test = function(a:: int, b::int):: Rec; entry() {
+ {a + b, y = 2}
+ }
+)";
+
+ auto man = XreateManager::prepare(move(code));
+ man->run();
+}
+
+TEST(Containers, DONE_RecUpdateByList1){
+ string code = R"(
+ Rec = type {x:: int, y:: int}.
+ test = function(a:: int, b::int):: Rec; entry() {
+ r = {0, y = 2}:: Rec.
+
+ r : {a + b}
+ }
+)";
+
+ auto man = XreateManager::prepare(move(code));
+ man->run();
+}
+
+TEST(Containers, DONE_RecUpdateByListIndex1){
+ string code = R"(
+ Rec = type {x:: int, y:: int}.
+ test = function(a:: int, b::int):: int; entry() {
+ r1 = undef:: Rec.
+ r2 = r1 : {[1] = b, [0] = a}:: Rec.
+
+ r2["x"]
+ }
+)";
+
+ auto man = XreateManager::prepare(move(code));
+ Fn2Args program = (Fn2Args) man->run();
+ ASSERT_EQ(10, program(10, 11));
+}
+
+TEST(Containers, DONE_RecUpdateInLoop1){
+ FILE* code = fopen("scripts/containers/RecUpdateInLoop1.xreate", "r");
+ assert(code != nullptr);
+
+ auto man = XreateManager::prepare(code);
+ Fn1Args program = (Fn1Args) man->run();
+ ASSERT_EQ(11, program(10));
+}
+
+TEST(Containers, DONE_ArrayInit1){
+ XreateManager* man = XreateManager::prepare(
+R"Code(
+main = function(x:: int):: int; entry() {
+ a = {1, 2, 3}:: [int].
+ a[x]
+}
+)Code");
void* mainPtr = man->run();
- int (*main)(int) = (int (*)(int))mainPtr;
+ Fn1Args main = (Fn1Args) mainPtr;
ASSERT_EQ(2, main(1));
delete man;
}
+TEST(Containers, DONE_ArrayUpdate1){
+ XreateManager* man = XreateManager::prepare(R"(
+main = function(x::int):: int; entry()
+{
+ a = {1, 2, 3}:: [int]; csize(5).
+ b = a : {[1] = x}:: [int]; csize(5).
+ b[1]
+}
+)");
+
+ void* mainPtr = man->run();
+ Fn1Args main = (Fn1Args) mainPtr;
+ ASSERT_EQ(2, main(2));
+
+ delete man;
+}
+
TEST(Containers, ListAsArray2){
XreateManager* man = XreateManager::prepare(
R"Code(
// CONTAINERS
import raw("scripts/dfa/ast-attachments.lp").
import raw("scripts/containers/containers.lp").
main = function:: int;entry {
a= {1, 2, 3}:: [int].
b= loop map(a->el:: int):: [int]{
2 * el
}.
sum = loop fold(b->el:: int, 0->acc):: int {
acc + el
}.
sum
}
)Code");
void* mainPtr = man->run();
- int (*main)() = (int (*)())mainPtr;
+ FnNoArgs main = (FnNoArgs) mainPtr;
ASSERT_EQ(12, main());
delete man;
}
+TEST(Containers, Doc_RecField1){
+ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecField1");
+ XreateManager::prepare(move(code_Variants1));
+
+ ASSERT_TRUE(true);
+}
+
+TEST(Containers, Doc_RecUpdate1){
+ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecUpdate1");
+ XreateManager::prepare(move(code_Variants1));
+
+ ASSERT_TRUE(true);
+}
+
TEST(Containers, ContanierLinkedList1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST* ast = parser.root->finalize();
CodeScope* body = ast->findFunction("test")->getEntryScope();
const Symbol symb_chilrenRaw{body->getSymbol("childrenRaw"), body};
containers::ImplementationLinkedList iLL(symb_chilrenRaw);
ASSERT_EQ(true, static_cast<bool>(iLL));
ASSERT_EQ("next", iLL.fieldPointer);
Implementation impl = Implementation::create(symb_chilrenRaw);
ASSERT_NO_FATAL_FAILURE(impl.extract<ON_THE_FLY>());
ImplementationRec<ON_THE_FLY> recOnthefly = impl.extract<ON_THE_FLY>();
ASSERT_EQ(symb_chilrenRaw, recOnthefly.source);
}
TEST(Containers, Implementation_LinkedListFull){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
std::unique_ptr<XreateManager> program(XreateManager::prepare(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
- int answer = main();
+ intmax_t answer = main();
ASSERT_EQ(17, answer);
fclose(input);
}
TEST(Containers, Doc_Intr_1){
string example = R"Code(
import raw("scripts/containers/containers.lp").
test = function:: int; entry
{
<BODY>
x
}
)Code";
string body = getDocumentationExampleById("documentation/Concepts/containers.xml", "Intr_1");
replace(example, "<BODY>", body);
XreateManager* xreate = XreateManager::prepare(move(example));
- IntFn program = (IntFn) xreate->run();
-
- int result = program();
+ FnNoArgs program = (FnNoArgs) xreate->run();
+
+ intmax_t result = program();
ASSERT_EQ(1, result);
}
TEST(Containers, Doc_OpAccessSeq_1){
string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "OpAccessSeq_1");
XreateManager* xreate = XreateManager::prepare(move(example));
- IntFn program = (IntFn) xreate->run();
-
- int result = program();
+ FnNoArgs program = (FnNoArgs) xreate->run();
+
+ intmax_t result = program();
ASSERT_EQ(15, result);
}
TEST(Containers, Doc_OpAccessRand_1){
string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "OpAccessRand_1");
XreateManager* xreate = XreateManager::prepare(move(example));
- IntFn program = (IntFn) xreate->run();
-
- int result = program();
+ FnNoArgs program = (FnNoArgs) xreate->run();
+
+ intmax_t result = program();
ASSERT_EQ(2, result);
}
TEST(Containers, Doc_ASTAttach_1){
string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "ASTAttach_1");
string outputExpected = "containers_impl(s(1,-2,0),onthefly)";
XreateManager* xreate = XreateManager::prepare(move(example));
testing::internal::CaptureStdout();
xreate->run();
std::string outputActual = testing::internal::GetCapturedStdout();
ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
}
+
+TEST(Containers, IntrinsicArrInit1){
+ XreateManager* man = XreateManager::prepare(
+
+R"Code(
+FnAnns = type predicate {
+ entry
+}
+
+main = function(x:: int):: int; entry() {
+ a{0} = intrinsic array_init(16):: [int].
+ a{1} = a{0} + {15: 12}
+}
+)Code");
+}
diff --git a/cpp/tests/dimensions.cpp b/cpp/tests/dimensions.cpp
new file mode 100644
index 0000000..60e41c8
--- /dev/null
+++ b/cpp/tests/dimensions.cpp
@@ -0,0 +1,190 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * ast.cpp
+ *
+ * Created on: Jan, 2020
+ * Author: pgess <v.melnychenko@xreate.org>
+ */
+
+#include "xreatemanager.h"
+#include "analysis/transcendtarget.h"
+#include "gtest/gtest.h"
+
+using namespace std;
+using namespace xreate;
+
+TEST(Dimensions, AST_AnnotationTypeEmpty){
+ std::string code = R"(
+ my-rec-t = type predicate{}
+ )";
+
+ ASSERT_DEATH(XreateManager::prepare(move(code)), "-- line 2 col 31: Predicate type can't be empty.");
+}
+
+TEST(Dimensions, AST_RecognizeAnnIdents){
+ std::string code = R"(
+ my-func1 = function:: int; UnknownAnn() {0}
+ my-func2 = function:: int; UnknownIdent {0}
+ )";
+
+ ASSERT_DEATH(XreateManager::prepare(move(code)),
+ "-- line 2 col 32: Undefined predicate\n-- line 3 col 32: Undefined scope");
+}
+
+TEST(Dimensions, CompileFnAnn1){
+ std::string code = R"(
+ FnAnns = type predicate{
+ FnMyAnn
+ }.
+ myf = function:: int; FnMyAnn() {
+ 0
+ }
+ )";
+
+ auto xreate = details::tier2::XreateManager::prepare(move(code));
+ xreate->registerPass(new TranscendPass(xreate), PassId::TranscendPass);
+ xreate->executePasses();
+ testing::internal::CaptureStdout();
+ xreate->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual;
+
+ string outputExpected = "bind_func(\"myf\",fnMyAnn)";
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Dimensions, CompileScopeAnn1){
+ std::string code = R"(
+ ScopeAnns = type predicate{
+ MyScopeAnn
+ }.
+
+ myf = function:: int {
+ context:: MyScopeAnn().
+ 0
+ }
+ )";
+
+ auto xreate = details::tier2::XreateManager::prepare(move(code));
+ xreate->registerPass(new TranscendPass(xreate), PassId::TranscendPass);
+ xreate->executePasses();
+ testing::internal::CaptureStdout();
+ xreate->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual;
+ string outputExpected = "bind_scope(0, myScopeAnn)";
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Dimensions, CompileScopeVar1){
+ std::string code = R"(
+ ScopeAnns = type predicate{
+ MyScopeAnn(int)
+ }.
+
+ myf = function:: int {
+ x = MyScopeAnn(8):: ScopeAnns.
+ if (0>2):: int
+ {
+ context:: x.
+ 0
+ } else {0}
+ }
+ )";
+
+ auto xreate = details::tier2::XreateManager::prepare(move(code));
+ xreate->registerPass(new TranscendPass(xreate), PassId::TranscendPass);
+ xreate->executePasses();
+ testing::internal::CaptureStdout();
+ xreate->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual;
+ string outputExpected = "bind_scope(1,myScopeAnn(8))";
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Dimensions, RepresentDeepAnn1){
+ std::string code = R"(
+figure = type predicate {
+ circle(int)
+}
+
+fn-ann = type predicate {
+ entry, demand(figure)
+}
+
+dem-fn = function:: int {0}
+
+main-fn = function(x::int, y::int):: int; entry() {
+ fig = circle(x+y):: figure.
+ dem-fn():: int; demand(fig)
+}
+ )";
+
+ auto xreate = details::tier2::XreateManager::prepare(move(code));
+ xreate->registerPass(new TranscendPass(xreate), PassId::TranscendPass);
+ xreate->executePasses();
+ testing::internal::CaptureStdout();
+ xreate->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ string outputExpected = "bind(s(0,-2,1),demand(circle(a(41))))";
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Dimensions, CompileDeepAnn1){
+ std::string code = R"(
+figure = type predicate {
+ oval, circle(int), square
+}
+
+fn-ann = type predicate {
+ entry, demand(figure)
+}
+
+fn-dem = function:: int {0}
+
+main-fn = function(x::int, y::int):: int; entry() {
+ fig = circle(x+y):: figure.
+ fn-dem():: int; demand(fig)
+}
+ )";
+
+ auto xreate = details::tier2::XreateManager::prepare(move(code));
+ xreate->transcend->addRawScript(R"(
+ func_demand("fn-dem", "figf", "figure").
+ func_supply(Site, "figf", Value):- bind(Site, demand(Value)).
+ )");
+
+ xreate->registerPass(new TranscendPass(xreate), PassId::TranscendPass);
+ xreate->executePasses();
+ //testing::internal::CaptureStdout();
+ xreate->analyse();
+ xreate->run();
+
+
+ //std::string outputActual = testing::internal::GetCapturedStdout();
+ //string outputExpected = "bind(s(0,-2,1),demand(circle(a(41))))";
+ //ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Dimensions, DISABLED_Test1){
+ string s =
+R"(
+ my-ann = type annotation {
+ circle,
+ square
+ }
+
+ my-func = function:: int; entry
+ {
+ x = circle():: my-ann.
+
+ context:: x
+ {
+ 0
+ }
+ }
+)";
+ cout << s;
+}
\ No newline at end of file
diff --git a/cpp/tests/exploitation.cpp b/cpp/tests/exploitation.cpp
index 8316438..d0ba5fd 100644
--- a/cpp/tests/exploitation.cpp
+++ b/cpp/tests/exploitation.cpp
@@ -1,63 +1,64 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* exploitation.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on February 15, 2018, 6:17 PM
*/
#include "xreatemanager.h"
#include "analysis/cfagraph.h"
#include "pass/cfapass.h"
#include "pass/cfatemporalseqpass.h"
#include "supplemental/docutils.h"
-#include "supplemental/defines.h"
+#include "supplemental/basics.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace xreate::cfa;
using namespace std;
TEST(Exploitation, Doc_ResourceInit_1) {
string example = getDocumentationExampleFromFile("scripts/exploitation/test1.xreate");
string body = getDocumentationExampleById("documentation/exploitation.xml", "ResourceInit_1");
replace(example, "<BODY>", body);
details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(example));
CFATemporalSeqPass* pass = new CFATemporalSeqPass(man);
man->registerPass(pass, PassId::CFATemporalSeqPass);
man->analyse();
int (* main)() = (int (*)()) man->run();
int result = main();
delete pass;
delete man;
ASSERT_EQ(1, result);
}
TEST(Exploitation, Doc_ExampleEov_1){
string code = getDocumentationExampleFromFile("scripts/execution-order/test-1.xreate");
string codeSpecializations = getDocumentationExampleById("documentation/index.xml", "ExampleEov_1_Specializations");
string script = getDocumentationExampleFromFile("/private/prg/code/xreate/scripts/execution-order/test-1.assembly.lp");
string scriptExpectation = getDocumentationExampleById("documentation/index.xml", "ExampleEov_1_Expectation");
string scriptRegistration = getDocumentationExampleById("documentation/index.xml", "ExampleEov_1_Registration");
replace(script, "<insert ExampleEov_1_Expectation>", scriptExpectation);
replace(script, "<insert ExampleEov_1_Registration>", scriptRegistration);
- replace(code, "<insert ExampleEov_1_Specializations>", codeSpecializations);
-
+ replace(code, "<insert ExampleEov_1_Specializations>", codeSpecializations);
+
+ std::cout << code << std::endl;
auto man = details::tier1::XreateManager::prepare(move(code));
man->transcend->addRawScript(move(script));
man->analyse();
FnNoArgs program = (FnNoArgs)man->run();
delete man;
testing::internal::CaptureStdout();
program();
std::string outputActual = testing::internal::GetCapturedStdout();
ASSERT_NE(std::string::npos, outputActual.find("HeaderBodyFooter"));
}
\ No newline at end of file
diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp
index 4609b15..a833453 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,485 +1,476 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* interpretation.cpp
*
* Created on: -
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "attachments.h"
using namespace xreate;
#include "xreatemanager.h"
#include "compilation/targetinterpretation.h"
-#include "analysis/interpretation.h"
#include "supplemental/docutils.h"
#include "gtest/gtest.h"
#include "boost/scoped_ptr.hpp"
//#define FRIENDS_INTERPRETATION_TESTS \
// friend class ::Modules_AST2_Test; \
// friend class ::Modules_Discovery1_Test; \
// friend class ::Modules_Solve1_Test;
#include "pass/interpretationpass.h"
using namespace xreate::grammar::main;
using namespace xreate::interpretation;
using namespace std;
TEST(Interpretation, Analysis_StatementIF_1) {
XreateManager* man = XreateManager::prepare(
R"Code(
main = function::bool {
x = "a":: string.
- y = if (x=="b"):: bool; i12n(on) {
+ y = if (x=="b"):: bool; i12n(on()) {
true
} else {
false
}.
y
}
)Code");
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
InterpretationData &dataSymbolY = Attachments::get<InterpretationData>(symbolY);
ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution);
}
TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1) {
XreateManager* man = XreateManager::prepare(
R"Code(
main = function(x:: int):: int {
- comm= "inc":: string; i12n(on).
+ comm= "inc":: string; i12n(on()).
y = if (comm == "inc")::int {x+1} else {x}.
y
}
)Code");
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
InterpretationData &dataSymbolY = Attachments::get<InterpretationData>(symbolY);
ASSERT_EQ(CMPL_ONLY, dataSymbolY.resolution);
ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
}
TEST(Interpretation, StatementCall_RecursionIndirect_1) {
XreateManager* man = XreateManager::prepare(
R"Code(
searchNemo = function(data:: Data):: bool
{
if (data == "nemo"):: bool
{false} else {searchDory(data)}
}
searchDory = function(data:: Data):: bool
{
if (data == "dory"):: bool
{true} else {searchNemo(data)}
}
- entry = function:: bool; entry {
- searchNemo(""):: bool; i12n(on)
+ entry = function:: bool; entry() {
+ searchNemo(""):: bool; i12n(on())
}
)Code");
InterpretationPass* pass = new InterpretationPass(man);
ASSERT_DEATH(pass->run(), "Indirect recursion detected");
}
TEST(Interpretation, PartialIntr_1) {
XreateManager* man = XreateManager::prepare(
R"Code(
- evaluate= function(argument:: num, code:: string; i12n(on)):: num {
- switch(code):: num
+ evaluate= function(argument:: int, code:: string; i12n(on())):: int {
+ switch(code):: int
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
case default {argument}
}
- main = function:: int; entry {
- commands= {"inc", "double", "dec"}:: [string]; i12n(on).
+ main = function:: int; entry() {
+ commands= {"inc", "double", "dec"}:: [string]; i12n(on()).
loop fold(commands->comm::string, 10->operand):: int
{
evaluate(operand, comm)
}
}
)Code");
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
ManagedFnPtr fnEvaluate = man->root->findFunction("evaluate");
InterpretationResolution resFnEvaluate = pass->process(fnEvaluate);
ASSERT_EQ(CMPL_ONLY, resFnEvaluate);
ASSERT_TRUE(FunctionInterpretationHelper::needPartialInterpretation(fnEvaluate));
const Expression &exprLoop = man->root->findFunction("main")->__entry->getBody();
Symbol symbCallEv{{0, versions::VERSION_NONE}, exprLoop.blocks.front()};
InterpretationData dataCallEv = Attachments::get<InterpretationData>(symbCallEv);
ASSERT_EQ(CMPL_ONLY, dataCallEv.resolution);
ASSERT_EQ(CALL_INTERPRET_PARTIAL, dataCallEv.op);
}
TEST(Interpretation, PartialIntr_3) {
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
Command= type variant {INC, DEC, DOUBLE}.
- evaluate= function(argument:: num, code:: Command; i12n(on)):: num {
+ evaluate= function(argument:: int, code:: Command; i12n(on())):: int {
switch variant(code)::int
case (INC) {argument + 1}
case (DEC) {argument - 1}
case (DOUBLE) {argument * 2}
}
- main = function::int; entry {
- commands= {INC(), DOUBLE(), DEC()}:: [Command]; i12n(on).
+ main = function::int; entry() {
+ commands= {INC(), DOUBLE(), DEC()}:: [Command]; i12n(on()).
loop fold(commands->comm::Command, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code");
man->analyse();
if(!man->isPassRegistered(PassId::InterpretationPass)) {
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(21, result);
}
TEST(Interpretation, PartialIntr_4) {
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
Command= type variant {INC, DEC, DOUBLE}.
- evaluate= function(argument:: num, code:: Command; i12n(on)):: num {
- switch variant(code)::num
+ evaluate= function(argument:: int, code:: Command; i12n(on())):: int {
+ switch variant(code)::int
case (INC) {argument + 1}
case (DEC) {argument - 1}
case (DOUBLE) {argument * 2}
}
- main = function::int; entry {
+ main = function::int; entry() {
evaluate(4, DEC())
}
)Code");
man->analyse();
if(!man->isPassRegistered(PassId::InterpretationPass)) {
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(3, result);
}
TEST(Interpretation, SwitchVariant) {
xreate::XreateManager* man = xreate::XreateManager::prepare(
R"Code(
-OneArgument = type{x::int}.
-TWoArgument = type {x::int, y::int}.
-
Command= type variant {
- ADD::TwoArguments,
- DEC:: OneArgument,
- DOUBLE::OneArgument
+ ADD(x::int, y::int),
+ DEC(x::int),
+ DOUBLE(x::int)
}.
-main = function::int; entry{
- program = ADD({x=2, y=3})::Command; i12n(on).
+main = function::int; entry(){
+ program = ADD(2, 3)::Command; i12n(on()).
switch variant(program)::int
case (ADD) {program["x"]+program["y"]}
case (DEC) {1}
case (DOUBLE) {2}
}
)Code");
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(5, result);
}
TEST(Interpretation, SwitchVariantAlias) {
xreate::XreateManager* man = xreate::XreateManager::prepare(
R"Code(
-OneArgument = type {x::int}.
-TWoArgument = type {x::int, y::int}.
-
Command= type variant {
- ADD::TwoArguments,
- DEC:: OneArgument,
- DOUBLE::OneArgument
+ ADD(x::int, y::int),
+ DEC(x::int),
+ DOUBLE(x::int)
}.
-main = function::int; entry{
- program = {ADD({x=2, y=3}), DEC({x=8})}::[Command]; i12n(on).
+main = function::int; entry(){
+ program = {ADD(2, 3), DEC(8)}::[Command]; i12n(on()).
- switch variant(program[0]->program::Command)::int
- case (ADD) {program["x"]+program["y"]}
- case (DEC) {1}
- case (DOUBLE) {2}
+ switch variant(program[0]->program::Command)::int
+ case (ADD) {program["x"]+program["y"]}
+ case (DEC) {1}
+ case (DOUBLE) {2}
}
)Code");
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(5, result);
}
TEST(Interpretation, Multiindex1) {
std::string script2 =
R"Code(
- extract = function(program::unknType)::int; i12n(on){
+ extract = function(program::unknType)::int; i12n(on()){
program["arguments"][1]
}
- main = function::int; entry {
- x = {arguments = {10, 9, 8, 7}}:: unknType; i12n(on).
+ main = function::int; entry() {
+ x = {arguments = {10, 9, 8, 7}}:: unknType; i12n(on()).
extract(x)
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script2)));
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(9, result);
}
TEST(InterpretationExamples, Regexp1) {
FILE* input = fopen("scripts/dsl/regexp.xreate", "r");
assert(input != nullptr);
std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(4, result);
}
TEST(Interpretation, Variant1) {
std::string script =
R"Code(
-Data = type {Num:: [int], String::string}.
-
DataPacked = type variant {
- Var1:: Data,
- Var2:: Data
+ Var1(Num:: [int], String::string),
+ Var2(Num:: [int], String::string)
}.
extractInt = function(data::DataPacked):: int {
- resultWrong = 0 :: int.
+ resultWrong = 0 :: int.
- switch variant(data)::int
- case (Var1) {data["Num", 0]}
- case (Var2) {resultWrong}
+ switch variant(data)::int
+ case (Var1) {data["Num", 0]}
+ case (Var2) {resultWrong}
}
-main = function :: int; entry {
- dataActual = 10.
- dataPacked = Var1({Num = {dataActual}, String = "whatever"}):: DataPacked.
+main = function :: int; entry() {
+ dataActual = {10}:: [int].
+ dataPacked = Var1(dataActual, "whatever"):: DataPacked.
- extractInt(dataPacked):: int; i12n(on)
+ extractInt(dataPacked):: int; i12n(on())
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
int (* main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(10, result);
}
TEST(Interpretation, Doc_Intr_1) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "Intr_1");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
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, Doc_FnIntr_1) {
string example1 = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "FnIntr_1");
string example2 = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "Alt_FnIntr_1");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example1));
man->analyse();
InterpretationPass* pass;
if(man->isPassRegistered(PassId::InterpretationPass)) {
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
unsigned char (* main)() = (unsigned char (*)()) man->run();
unsigned char result = main();
ASSERT_EQ(1, result);
XreateManager* man2 = XreateManager::prepare(move(example2));
ASSERT_TRUE(true);
}
TEST(Interpretation, Doc_FnIntr_2) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "FnIntr_2");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
InterpretationPass* pass;
if(man->isPassRegistered(PassId::InterpretationPass)) {
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
unsigned char (* main)() = (unsigned char (*)()) man->run();
unsigned char result = main();
ASSERT_EQ(1, result);
}
TEST(Interpretation, Doc_FnIntr_3) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "FnIntr_3");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
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(ANY, resolutionActual);
unsigned char (* main)() = (unsigned char (*)()) man->run();
unsigned char result = main();
ASSERT_NE(0, result);
}
TEST(Interpretation, Doc_LateIntr_1) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "LateIntr_1");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
InterpretationPass* pass;
if(man->isPassRegistered(PassId::InterpretationPass)) {
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (* main)(int) = (int (*)(int)) man->run();
int result = main(1);
ASSERT_EQ(2, result);
}
TEST(Interpretation, Doc_LateIntr_2) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "LateIntr_2");
string example2 = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "Alt_LateIntr_2");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
InterpretationPass* pass;
if(man->isPassRegistered(PassId::InterpretationPass)) {
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
const ManagedFnPtr &funcMain = man->root->findFunction("main");
InterpretationData &dataBody = Attachments::get<InterpretationData>(funcMain);
ASSERT_EQ(FOLD_INTERPRET_INPUT, dataBody.op);
int (* main)(int) = (int (*)(int)) man->run();
int result = main(10);
ASSERT_EQ(21, result);
XreateManager* man2 = XreateManager::prepare(move(example2));
ASSERT_TRUE(true);
}
TEST(Interpretation, Doc_LateFnIntr_1) {
string example = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "LateFnIntr_1");
string example2 = getDocumentationExampleById("documentation/Concepts/interpretation.xml", "Alt_LateFnIntr_1");
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(move(example));
man->analyse();
if(!man->isPassRegistered(PassId::InterpretationPass)) {
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (* main)(int) = (int (*)(int)) man->run();
int result = main(10);
ASSERT_EQ(21, result);
XreateManager* man2 = XreateManager::prepare(move(example2));
ASSERT_TRUE(true);
}
//TOTEST call indirect recursion(w/o tags)
//TASk implement and test Loop Inf (fix acc types in coco grammar)
diff --git a/cpp/tests/latex.cpp b/cpp/tests/latex.cpp
index 7fea3ef..3db5c5e 100644
--- a/cpp/tests/latex.cpp
+++ b/cpp/tests/latex.cpp
@@ -1,358 +1,358 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 25, 2018, 5:42 PM
*
* \file latex.cpp
* \brief Testing of latex
*/
#include "xreatemanager.h"
#include "pass/compilepass.h"
#include "transcendlayer.h"
#include "query/latex.h"
-#include "compilation/latex.h"
+#include "compilation/demand.h"
#include "aux/xreatemanager-decorators.h"
-#include "compilation/scopedecorators.h"
+#include "compilation/decorators.h"
#include "llvmlayer.h"
#include "supplemental/docutils.h"
-#include "supplemental/defines.h"
+#include "supplemental/basics.h"
#include <boost/format.hpp>
#include <gtest/gtest.h>
using namespace xreate::latex;
using namespace xreate::latereasoning;
using namespace xreate::compilation;
using namespace xreate;
using namespace std;
TEST(Latex, Script_NestedScopePropagation_1) {
std::string program =
R"CODE(
import raw("scripts/cfa/context.lp").
fn = function:: int; entry
{
context:: test1.
if(1==11)::int {2} else {3}
}
)CODE";
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
CodeScope* blockTrue = man->root->findFunction("fn")->getEntryScope()->getBody().blocks.front();
auto blockTrueP = man->transcend->pack(blockTrue);
boost::format formatAlias("alias(%1%, %2%).");
man->transcend->addRawScript((formatAlias % blockTrueP % "block1").str());
man->transcend->addRawScript(
R"SCRIPT(
success1:- bind_scope(Block1, test1, strong); alias(Block1, block1).
)SCRIPT");
man->analyse();
ASSERT_EQ(1, man->transcend->query("success1").size());
}
TEST(Latex, Script_DemAndDecision_1) {
std::string program =
R"CODE(
import raw("scripts/cfa/context.lp").
a = function:: int
{
context:: forC(a).
c()
}
b = function:: int
{
context:: forC(b).
c()
}
c = function:: int {0}
main = function:: int; entry
{
a() + b()
}
)CODE";
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
CodeScope* blockC = man->root->findFunction("c")->getEntryScope();
auto blockCP = man->transcend->pack(blockC);
boost::format formatAlias("alias(%1%, %2%).");
man->transcend->addRawScript((formatAlias % blockCP % "blockC").str());
man->transcend->addRawScript(
R"SCRIPT(
latex_scope_demand(BlockC, forC):- alias(BlockC, blockC).
latex_registered_subjects(forC, Variant):- bind_scope(_, Variant, strong); Variant = forC(_).
)SCRIPT");
man->analyse();
ASSERT_EQ(1, man->transcend->query("latex_fn_demand").size());
ASSERT_EQ(2, man->transcend->query("latex_decision").size());
}
TEST(Latex, LatexQuery_getFnDemand_1){
std::string program =
R"CODE(
import raw("scripts/cfa/context.lp").
main = function:: int; entry
{
context:: alias(blockMain).
0
}
)CODE";
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
man->transcend->addRawScript(
R"SCRIPT(
latex_scope_demand(BlockC, forC):- bind_scope(BlockC, alias(blockMain), strong).
latex_registered_subjects(forC, decisionSome).
)SCRIPT");
LatexQuery* query = new LatexQuery();
man->transcend->registerQuery(query, QueryId::LatexQuery);
man->analyse();
Demand demand = query->getFnDemand("main");
ASSERT_EQ(1, demand.size());
ASSERT_STREQ("forC", demand.front().c_str());
}
TEST(Latex, LatexQuery_getDecision_static_1){
std::string program =
R"CODE(
import raw("scripts/cfa/context.lp").
a = function:: int {context::decisionSome. c()}
b = function:: int {c()}
c = function:: int {context:: alias(blockC). 0}
)CODE";
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
man->transcend->addRawScript(
R"SCRIPT(
latex_scope_demand(BlockC, forC):- bind_scope(BlockC, alias(blockC), strong).
latex_registered_subjects(forC, decisionSome).
)SCRIPT");
LatexQuery* query = new LatexQuery();
man->transcend->registerQuery(query, QueryId::LatexQuery);
man->analyse();
- LateAnnotation decisionLA = query->getDecision("forC", man->root->findFunction("a")->getEntryScope());
+ LateAnnotation decisionLA = query->getValue("forC", man->root->findFunction("a")->getEntryScope());
auto decisionGS = decisionLA.select({}, man->root, man->transcend);
ASSERT_TRUE(decisionGS);
decisionGS->print(cout);
cout << endl;
auto decisionTuple = man->transcend->parse<Gringo::Symbol, Gringo::Symbol, string>(*decisionGS);
string decision = get<2>(decisionTuple);
ASSERT_STREQ("decisionSome", decision.c_str());
}
TEST(Latex, Compilation_1) {
std::string program =
R"CODE(
a = function:: int
{0}
main = function:: int; entry
{
a()
}
)CODE";
string script =
R"SCRIPT(
latex_fn_demand(%1%, subject1).
latex_decision(%2%, subject1, 5).
latex_registered_subjects(subject1, 1).
latex_registered_subjects(subject1, 5).
)SCRIPT";
- typedef LatexBruteFunctionDecorator<compilation::BasicFunctionUnit> FnImpl;
+ typedef ExtraArgsBruteFnDecorator<compilation::BasicFunctionUnit> FnImpl;
typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
ScopePacked scopeMainP = man->transcend->pack(man->root->findFunction("main")->getEntryScope());
boost::format format(script);
man->transcend->addRawScript((format % "a" % scopeMainP).str());
man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery);
man->analyse();
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(man.get()));
compiler->run();
man->llvm->initJit();
int(*fnMain)() = (int(*)())man->llvm->getFunctionPointer(compiler->getEntryFunction());
ASSERT_EQ(0, fnMain());
}
//
//TEST(Latex, Full1) {
// std::string program =
// R"CODE(
// import raw("scripts/cfa/context.lp").
//
// a = function:: int
// {
// context:: forC(a).
// c()
// }
//
// b = function:: int
// {
// context:: forC(b).
// c()
// }
//
// c = function:: int {0}
//
// main = function:: int; entry
// {
// a() + b()
// }
// )CODE";
//
// string script =
// R"SCRIPT(
// alias(%1%, scopeC).
// latex_scope_demand(ScopeC, forC) :- alias(ScopeC, scopeC).
// latex_registered_subjects(forC, forC(a)).
// latex_registered_subjects(forC, forC(b)).
// )SCRIPT";
//
-// typedef LatexBruteFunctionDecorator<compilation::BasicFunctionUnit> FnImpl;
+// typedef DemandBruteFnDecorator<compilation::BasicFunctionUnit> FnImpl;
// typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
//
// std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
// ScopePacked scopeMainP = man->transcend->pack(man->root->findFunction("main")->getEntryScope());
// auto scopeCP = man->transcend->pack(man->root->findFunction("c")->getEntryScope());
// boost::format format(script);
// man->transcend->addRawScript((format %scopeCP).str());
// man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery);
// man->analyse();
//
// std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(man.get()));
// compiler->run();
// man->llvm->print();
//}
//
TEST(Latex, Compilation_TransitFn1){
std::string program =
R"CODE(
import raw("scripts/cfa/context.lp").
branchA = function:: int
{
context:: sink_a.
fnTransit()
}
branchB = function:: int
{
context:: sink_b.
fnTransit()
}
fnSink = function:: int {0}
fnTransit = function:: int {fnSink()}
main = function:: int; entry
{
branchA() + branchB()
}
)CODE";
string script =
R"SCRIPT(
alias(scopeSink, %1%).
latex_scope_demand(ScopeSink, sink):- alias(scopeSink, ScopeSink).
latex_registered_subjects(sink, sink_a).
latex_registered_subjects(sink, sink_b).
)SCRIPT";
- typedef LatexBruteFunctionDecorator<compilation::BasicFunctionUnit> FnImpl;
+ typedef ExtraArgsBruteFnDecorator<compilation::BasicFunctionUnit> FnImpl;
typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
CodeScope* scopeSink = man->root->findFunction("fnSink")->getEntryScope();
auto scopeSinkP = man->transcend->pack(scopeSink);
ScopedSymbol argLatexSS{1, -1};
Symbol argLatexS{argLatexSS, scopeSink};
man->transcend->pack(argLatexS);
boost::format format(script);
man->transcend->addRawScript((format %scopeSinkP).str());
man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery);
man->analyse();
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(man.get()));
compiler->run();
man->llvm->print();
man->llvm->initJit();
int(*fnMain)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction());
int valueActual = fnMain();
ASSERT_EQ(0, valueActual);
}
TEST(Latex, Doc_Examples1){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Examples_1");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_Examples2){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Examples_2");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_ContextPropagation1){
std::string program =getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation1");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_ContextPropagation2){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation2");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_Latex1){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Latex1");
string script =
R"SCRIPT(
latef("compute").
latex_scope_demand(Scope, f_guarded(F)):-
cfa_call(Scope, F);
latef(F).
latex_registered_subjects(f_guarded(F), Guard):-
cfa_function_specializations(F, Guard);
latef(F).
late(TargetS, LatexParam, Guard, dfa_callguard(TargetS, Guard)):-
dfa_callfn(TargetS, FnGuarded);
latef(FnGuarded);
latex_symbol(FnCallerBody, f_guarded(FnGuarded), LatexParam);
TargetS=s(_,_, TargetScope);
scope_fnbody(TargetScope, FnCallerBody);
cfa_function_specializations(FnGuarded, Guard).
)SCRIPT";
auto man(XreateManager::prepare(move(program)));
man->transcend->addRawScript(move(script));
Fn3args fn = (Fn3args) man->run();
int resultActual = fn(1, 4, 3);
ASSERT_EQ(7, resultActual);
resultActual = fn(0, 4, 3);
ASSERT_EQ(1, resultActual);
}
\ No newline at end of file
diff --git a/cpp/tests/main.cpp b/cpp/tests/main.cpp
index 2df18c6..8905f18 100644
--- a/cpp/tests/main.cpp
+++ b/cpp/tests/main.cpp
@@ -1,24 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* main.cpp
*
* Created on: 00:00 Xreate Epoch
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "utils.h"
+#include "supplemental/basics.h"
#include <gtest/gtest.h>
using namespace std;
using namespace xreate;
int main(int argc, char **argv) {
testing::GTEST_FLAG(color) = "yes";
- string testsTemplate = Config::get("tests.template");
- string testsFilter = Config::get(string("tests.templates.") + testsTemplate);
+ string testsTemplate = Config::get("template");
+ string testsFilter = Config::get(string("templates.") + testsTemplate);
testing::GTEST_FLAG(filter) = testsFilter;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/cpp/tests/polymorph.cpp b/cpp/tests/polymorph.cpp
index 5a930bc..bc35f39 100644
--- a/cpp/tests/polymorph.cpp
+++ b/cpp/tests/polymorph.cpp
@@ -1,160 +1,266 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* polymorph.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on October 11, 2017, 8:37 PM
*/
#include "xreatemanager.h"
#include "ast.h"
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <list>
#include "gtest/gtest.h"
#include "query/polymorph.h"
#include "supplemental/docutils.h"
+#include "supplemental/basics.h"
using namespace xreate;
using namespace xreate::latereasoning;
using namespace xreate::polymorph;
using namespace std;
TEST(Polymorphs, ast1) {
- xreate::XreateManager* man = xreate::XreateManager::prepare(
- R"CODE(
- guard:: a {
- test = function:: int {0}
- }
+ xreate::XreateManager* man = xreate::XreateManager::prepare(R"CODE(
+ global-ann = type predicate {
+ entry
+ }
- guard:: b {
- test = function:: int {1}
- }
+ context-ann = type predicate {
+ a, b
+ }
- main = function:: int; entry { test() }
+ guard(::a) {
+ test = function:: int {0}
+ }
-)CODE");
+ guard(::b) {
+ test = function:: int {1}
+ }
- const std::list<ManagedFnPtr>& specs = man->root->getFunctionSpecializations("test");
- ASSERT_EQ(2, specs.size());
+ main = function:: int; entry() { test() }
+ )CODE");
- auto itSpecs = specs.begin();
- ASSERT_EQ("a", (*itSpecs)->guard.getValueString());
- itSpecs++;
- ASSERT_EQ("b", (*itSpecs)->guard.getValueString());
+ const std::list<ManagedFnPtr>& specs = man->root->getFnSpecializations("test");
+ ASSERT_EQ(2, specs.size());
+
+ auto itSpecs = specs.begin();
+ ASSERT_EQ("a", (*itSpecs)->guard.getValueString());
+ itSpecs++;
+ ASSERT_EQ("b", (*itSpecs)->guard.getValueString());
}
-TEST(Polymorphs, PolymorphQuery_Static_1) {
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
- R"CODE(
- import raw("scripts/dfa/polymorphism.lp").
+TEST(Polymorphs, Compile1){
+ xreate::XreateManager* man = xreate::XreateManager::prepare(R"CODE(
+ global-ann = type predicate {
+ entry, guarded(value::int)
+ }
- guard:: a {
- test = function:: int {0}
- }
+ context-ann = type predicate {
+ first(value::int), second
+ }
- guard:: b {
- test = function:: int {1}
- }
+ guard(data::first) {
+ test = function:: int {data["value"]}
+ }
- main = function:: int; entry { test()::int; callguard(b); dfa_polym(ret)}
+ guard(::second) {
+ test = function:: int {1}
+ }
-)CODE");
+ main = function:: int; entry()
+ {
+ x = 8:: int.
+ test()::int; guarded(x)
+ }
+ )CODE");
- man->analyse();
- PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
-
- const Expression& bodyE = man->root->findFunction("main")->getEntryScope()->getBody();
- LateAnnotation decisionLA = query->get(bodyE);
- ASSERT_EQ(1, decisionLA.guardedContent.size());
-
- auto decisionOptSymb = decisionLA.select({}, man->root, man->transcend);
- ASSERT_TRUE(decisionOptSymb);
-
- decisionOptSymb->print(cout);
- cout << endl;
- string guard = query->getValue(*decisionOptSymb).getValueString();
- ASSERT_STREQ("b", guard.c_str());
+ man->transcend->addRawScript(R"(func_supply_guard(Site, first(Data), "context-ann"):- bind(Site, guarded(Data)).)");
+ man->run();
}
-TEST(Polymorphs, PolymorphQuery_Late_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"CODE(
- Late = type variant{a, b}.
- main = function:: int; entry{key= a():: Late; test. key::int}
-)CODE");
+TEST(Polymorphs, Compile2){
+ xreate::XreateManager* man = xreate::XreateManager::prepare(R"CODE(
+ guard-pred = type predicate {
+ first(value::int), second
+ }
- man->transcend->addRawScript(
-R"RULE(
- late(S, S, a, dfa_callguard(S, a)):-
- bind(S, test).
-
- late(S, S, b, dfa_callguard(S, b)):-
- bind(S, test).
-)RULE");
- man->analyse();
- PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
-
- CodeScope* scopeMain = man->root->findFunction("main")->getEntryScope();
- Symbol keyS = Symbol{scopeMain->getSymbol("key"), scopeMain};
-
- Expression keyE = scopeMain->getDefinition(keyS);
- latereasoning::LateAnnotation answerLA = query->get(keyE);
- Expression valueB(Operator::VARIANT, {}); valueB.setValueDouble(1);
- auto answerRaw = answerLA.select({valueB}, man->root, man->transcend);
- ASSERT_TRUE(answerRaw);
- Expression answerE = query->getValue(*answerRaw);
- ASSERT_STREQ("b", answerE.getValueString().c_str());
-}
+ global-ann = type predicate {
+ entry, guarded(guard-pred)
+ }
+
+ guard(data ::first) {
+ test = function:: int {data["value"]}
+ }
+
+ guard(::second) {
+ test = function:: int {1}
+ }
-TEST(Polymorphs, PSCU_1){
- auto man = details::tier1::XreateManager::prepare(R"Code(
- Dom = type variant {guard1, guard2}.
-
- guard:: guard1 {
- compute = function :: int
- {0}
- }
-
- guard:: guard2 {
- compute = function :: int
- {1}
- }
-
- test = function:: int; entry
- {
- xLate = guard2():: Dom.
- y1= switch late (xLate:: Dom; alias(xLate)):: int
- {
- compute():: int; guardkey(xLate)
- }.
- y1
- }
- )Code");
-
- man->transcend->addRawScript(R"RAW(
- dom(guard1; guard2).
- late(Target, Key, Variant, dfa_callguard(Target, Variant)):-
- bind(Target, guardkey(Alias));
- bind(Key, alias(Alias));
- dom(Variant).
- )RAW");
- man->analyse();
- int (*program)() = (int (*)())man->run();
- int result = program();
-
- ASSERT_EQ(1, result);
+ main = function:: int; entry()
+ {
+ x = first(8):: guard-pred.
+ test()::int; guarded(x)
+ }
+ )CODE");
+
+ man->transcend->addRawScript(R"(func_supply_guard(Site, Guard, "guard-pred"):- bind(Site, guarded(Guard)).)");
+ man->run();
}
-TEST(Polymorphs, Doc_FnLvlPoly_1){
- string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "FnLvlPoly_1");
- auto man = XreateManager::prepare(move(example));
- ASSERT_TRUE(true);
+TEST(Polymorphs, CompileException1){
+
+ xreate::XreateManager* man = xreate::XreateManager::prepare(R"CODE(
+ Global-ann = type predicate {
+ entry
+ }
+
+ HandlerDivByZero = type {
+ ret:: int
+ }
+
+ Guards = type predicate {
+ fast,
+ safe(handlerZeroDiv:: HandlerDivByZero)
+ }
+
+ guard(:: fast) {
+ div = function(a::int, b::int) { a / b}
+ }
+
+ guard(handlers:: safe) {
+ div = function(a::int, b::int)::int
+ {
+ if (b != 0):: int
+ {a / b} else { handlers["handlerZeroDiv", "ret"] }
+ }
+ }
+
+ main = function:: int; entry()
+ {
+ handler = { ret = 11 } ::HandlerDivByZero.
+ div(8, 0):: int; safe(handler)
+ }
+)CODE");
+
+ man->transcend->addRawScript(R"(func_supply_guard(Site, Guard, "Guards"):- bind(Site, Guard).)");
+ FnNoArgs fn = (FnNoArgs) man->run();
+ int result = fn();
+ ASSERT_EQ(11, result);
}
-TEST(Polymorphs, Doc_LatePoly_1){
- string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "LatePoly_1");
- auto man = XreateManager::prepare(move(example));
- ASSERT_TRUE(true);
-}
\ No newline at end of file
+//TEST(Polymorphs, PolymorphQuery_Static_1) {
+// xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
+// R"CODE(
+// import raw("scripts/dfa/polymorphism.lp").
+//
+// guard:: a {
+// test = function:: int {0}
+// }
+//
+// guard:: b {
+// test = function:: int {1}
+// }
+//
+// main = function:: int; entry { test()::int; callguard(b); dfa_polym(ret)}
+//
+//)CODE");
+//
+// man->analyse();
+// PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
+//
+// const Expression& bodyE = man->root->findFunction("main")->getEntryScope()->getBody();
+// LateAnnotation decisionLA = query->get(bodyE);
+// ASSERT_EQ(1, decisionLA.guardedContent.size());
+//
+// auto decisionOptSymb = decisionLA.select({}, man->root, man->transcend);
+// ASSERT_TRUE(decisionOptSymb);
+//
+// decisionOptSymb->print(cout);
+// cout << endl;
+// string guard = query->getValue(*decisionOptSymb).getValueString();
+// ASSERT_STREQ("b", guard.c_str());
+//}
+//
+//TEST(Polymorphs, PolymorphQuery_Late_1){
+// xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
+//R"CODE(
+// Late = type variant{a, b}.
+// main = function:: int; entry{key= a():: Late; test. key::int}
+//)CODE");
+//
+// man->transcend->addRawScript(
+//R"RULE(
+// late(S, S, a, dfa_callguard(S, a)):-
+// bind(S, test).
+//
+// late(S, S, b, dfa_callguard(S, b)):-
+// bind(S, test).
+//)RULE");
+// man->analyse();
+// PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
+//
+// CodeScope* scopeMain = man->root->findFunction("main")->getEntryScope();
+// Symbol keyS = Symbol{scopeMain->getSymbol("key"), scopeMain};
+//
+// Expression keyE = scopeMain->getDefinition(keyS);
+// latereasoning::LateAnnotation answerLA = query->get(keyE);
+// Expression valueB(Operator::VARIANT, {}); valueB.setValueDouble(1);
+// auto answerRaw = answerLA.select({valueB}, man->root, man->transcend);
+// ASSERT_TRUE(answerRaw);
+// Expression answerE = query->getValue(*answerRaw);
+// ASSERT_STREQ("b", answerE.getValueString().c_str());
+//}
+//
+//TEST(Polymorphs, PSCU_1){
+// auto man = details::tier1::XreateManager::prepare(R"Code(
+// Dom = type variant {guard1, guard2}.
+//
+// guard:: guard1 {
+// compute = function :: int
+// {0}
+// }
+//
+// guard:: guard2 {
+// compute = function :: int
+// {1}
+// }
+//
+// test = function:: int; entry
+// {
+// xLate = guard2():: Dom.
+// y1= switch late (xLate:: Dom; alias(xLate)):: int
+// {
+// compute():: int; guardkey(xLate)
+// }.
+// y1
+// }
+// )Code");
+//
+// man->transcend->addRawScript(R"RAW(
+// dom(guard1; guard2).
+// late(Target, Key, Variant, dfa_callguard(Target, Variant)):-
+// bind(Target, guardkey(Alias));
+// bind(Key, alias(Alias));
+// dom(Variant).
+// )RAW");
+// man->analyse();
+// int (*program)() = (int (*)())man->run();
+// int result = program();
+//
+// ASSERT_EQ(1, result);
+//}
+//
+//TEST(Polymorphs, Doc_FnLvlPoly_1){
+// string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "FnLvlPoly_1");
+// auto man = XreateManager::prepare(move(example));
+// ASSERT_TRUE(true);
+//}
+//
+//TEST(Polymorphs, Doc_LatePoly_1){
+// string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "LatePoly_1");
+// auto man = XreateManager::prepare(move(example));
+// ASSERT_TRUE(true);
+//}
\ No newline at end of file
diff --git a/cpp/tests/polymorphism-dt.cpp b/cpp/tests/polymorphism-dt.cpp
new file mode 100644
index 0000000..b0765f6
--- /dev/null
+++ b/cpp/tests/polymorphism-dt.cpp
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * polymorphism-dt.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on 26/02/2020
+ */
+
+#include "xreatemanager.h"
+#include "ast.h"
+#include "pass/compilepass.h"
+#include "compilation/targetinterpretation.h"
+#include "gtest/gtest.h"
+#include "llvmlayer.h"
+
+using namespace xreate;
+using namespace xreate::interpretation;
+using namespace std;
+
+TEST(PDT, BuildDTTable1){
+ Attachments::init<I12nFunctionSpec>();
+ FILE* code = fopen("scripts/dfa/build-table.xreate", "r");
+ assert(code != nullptr);
+ auto man = xreate::details::tier2::XreateManager::prepare(code);
+ CompilePass* compiler = new compilation::CompilePassCustomDecorators<>(man);
+ TargetInterpretation* targetI12n = new interpretation::TargetInterpretation(man, compiler);
+ ManagedFnPtr fn = man->root->findFunction("buildTable");
+
+ I12nFunctionSpec fnI12nReport;
+ fnI12nReport.flagPartialInterpretation = true;
+ fnI12nReport.signature.push_back(INTR_ONLY);
+ fnI12nReport.signature.push_back(INTR_ONLY);
+ Attachments::put<I12nFunctionSpec>(fn, fnI12nReport);
+
+ PIFnSignature fnSignature;
+ fnSignature.declaration = fn;
+ fnSignature.bindings.push_back(Expression());
+ fnSignature.bindings.push_back(Expression(Atom<Number_t>(1)));
+
+ PIFunction* fnI12n = targetI12n->getFunction(move(fnSignature));
+ llvm::Function* fnRaw = fnI12n->compile();
+
+ man->llvm->print();
+
+// man->
+// PIFunction
+}
diff --git a/cpp/tests/problems.cpp b/cpp/tests/problems.cpp
new file mode 100644
index 0000000..df96bbd
--- /dev/null
+++ b/cpp/tests/problems.cpp
@@ -0,0 +1,112 @@
+//
+// Created by pgess on 26/03/2020.
+//
+
+#include "xreatemanager.h"
+#include "pass/compilepass.h"
+#include "llvmlayer.h"
+#include "supplemental/basics.h"
+
+#include "gtest/gtest.h"
+
+using namespace xreate;
+
+TEST(Problems, MinMax1){
+ struct Pair {intmax_t x; intmax_t y;};
+ typedef Pair (*FnPair)();
+
+ FILE* code = fopen("scripts/containers/minmax.xreate", "r");
+ assert(code != nullptr);
+
+ auto man = details::tier1::XreateManager::prepare(code);
+ LLVMLayer* llvm = man->llvm;
+ man->analyse();
+
+ std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<>(man));
+ compiler->prepare();
+ llvm::Function* fnMinMax1Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax1"))->compile();
+ llvm::Function* fnMinMax2Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax2"))->compile();
+ llvm::Function* fnMinMax3Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax3"))->compile();
+ llvm::Function* fnMinMax4Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax4"))->compile();
+ llvm::Function* fnMinMax5Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax5"))->compile();
+ llvm::Function* fnMinMax6Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax6"))->compile();
+ llvm::Function* fnMinMax7Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax7"))->compile();
+ llvm::Function* fnMinMax8Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax8"))->compile();
+ llvm::Function* fnMinMax9Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax9"))->compile();
+ llvm::Function* fnMinMax10Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax10"))->compile();
+ llvm::Function* fnMinMax11Raw = compiler->getFunctionUnit(man->root->findFunction("fn-minmax11"))->compile();
+ llvm->print();
+
+ llvm->initJit();
+ {
+ FnPair fnMinxMax1 = (FnPair) llvm->getFunctionPointer(fnMinMax1Raw);
+ Pair resultMinMax1 = fnMinxMax1();
+ ASSERT_EQ(3, resultMinMax1.x);
+ ASSERT_EQ(37, resultMinMax1.y);
+ }
+
+ {
+ FnNoArgs fnMinMax2 = (FnNoArgs) llvm->getFunctionPointer(fnMinMax2Raw);
+ intmax_t resultMinMax2 = fnMinMax2();
+ ASSERT_EQ(10, resultMinMax2);
+ }
+
+ {
+ FnNoArgs fnMinMax3 = (FnNoArgs) llvm->getFunctionPointer(fnMinMax3Raw);
+ intmax_t resultMinMax3 = fnMinMax3();
+ ASSERT_EQ(146, resultMinMax3);
+ }
+
+ {
+ FnNoArgs fnMinMax4 = (FnNoArgs) llvm->getFunctionPointer(fnMinMax4Raw);
+ intmax_t resultMinMax4 = fnMinMax4();
+ ASSERT_EQ(6, resultMinMax4);
+ }
+
+ {
+ FnPair fnMinMax5 = (FnPair) llvm->getFunctionPointer(fnMinMax5Raw);
+ Pair resultMinMax5 = fnMinMax5();
+ ASSERT_EQ(4, resultMinMax5.x);
+ ASSERT_EQ(11, resultMinMax5.y);
+ }
+
+ {
+ FnPair fnMinMax6 = (FnPair) llvm->getFunctionPointer(fnMinMax6Raw);
+ Pair resultMinMax6 = fnMinMax6();
+ ASSERT_EQ(2, resultMinMax6.x);
+ ASSERT_EQ(8, resultMinMax6.y);
+ }
+
+ {
+ FnPair fnMinMax7 = (FnPair) llvm->getFunctionPointer(fnMinMax7Raw);
+ Pair resultMinMax7 = fnMinMax7();
+ ASSERT_EQ(1, resultMinMax7.x);
+ ASSERT_EQ(3, resultMinMax7.y);
+ }
+
+ {
+ FnPair fnMinMax8 = (FnPair) llvm->getFunctionPointer(fnMinMax8Raw);
+ Pair resultMinMax8 = fnMinMax8();
+ ASSERT_EQ(2, resultMinMax8.x);
+ ASSERT_EQ(3, resultMinMax8.y);
+ }
+
+ {
+ FnPair fnMinMax9 = (FnPair) llvm->getFunctionPointer(fnMinMax9Raw);
+ Pair resultMinMax9 = fnMinMax9();
+ ASSERT_EQ(1, resultMinMax9.x);
+ ASSERT_EQ(8, resultMinMax9.y);
+ }
+
+ {
+ FnNoArgs fnMinMax10 = (FnNoArgs ) llvm->getFunctionPointer(fnMinMax10Raw);
+ intmax_t resultMinMax10 = fnMinMax10();
+ ASSERT_EQ(1, resultMinMax10);
+ }
+
+ {
+ FnNoArgs fnMinMax11 = (FnNoArgs ) llvm->getFunctionPointer(fnMinMax11Raw);
+ intmax_t resultMinMax11 = fnMinMax11();
+ ASSERT_EQ(8, resultMinMax11);
+ }
+}
\ No newline at end of file
diff --git a/cpp/tests/supplemental/basics.cpp b/cpp/tests/supplemental/basics.cpp
new file mode 100644
index 0000000..67bf827
--- /dev/null
+++ b/cpp/tests/supplemental/basics.cpp
@@ -0,0 +1,11 @@
+//
+// Created by pgess on 12/03/2020.
+//
+
+#include "basics.h"
+
+Config Config::__self = Config();
+
+Config::Config()
+: __storage{json_file{ "config/default.json" }}
+{}
\ No newline at end of file
diff --git a/cpp/tests/supplemental/basics.h b/cpp/tests/supplemental/basics.h
new file mode 100644
index 0000000..98562b0
--- /dev/null
+++ b/cpp/tests/supplemental/basics.h
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ *
+ * File: defines.h
+ * Author: pgess
+ *
+ * Created on May 7, 2019, 8:11 PM
+ */
+
+#include "jeayeson/jeayeson.hpp"
+#include <cstdint>
+
+#ifndef DEFINES_H
+#define DEFINES_H
+
+
+
+typedef intmax_t (*FnNoArgs)();
+typedef intmax_t (*Fn1Args)(intmax_t);
+typedef intmax_t (*Fn2Args)(intmax_t, intmax_t);
+typedef intmax_t (*Fn3Args)(intmax_t, intmax_t, intmax_t);
+
+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>();
+ }
+};
+
+#endif /* DEFINES_H */
+
diff --git a/cpp/tests/supplemental/defines.h b/cpp/tests/supplemental/defines.h
deleted file mode 100644
index f51b989..0000000
--- a/cpp/tests/supplemental/defines.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- *
- *
- * File: defines.h
- * Author: pgess
- *
- * Created on May 7, 2019, 8:11 PM
- */
-
-#ifndef DEFINES_H
-#define DEFINES_H
-
-typedef int (*FnNoArgs)();
-typedef int (*Fn1Args)(int);
-typedef int (*Fn2args)(int, int);
-typedef int (*Fn3args)(int, int, int);
-
-
-#endif /* DEFINES_H */
-
diff --git a/cpp/tests/transcend.cpp b/cpp/tests/transcend.cpp
index e7a53ac..e5d6436 100644
--- a/cpp/tests/transcend.cpp
+++ b/cpp/tests/transcend.cpp
@@ -1,93 +1,102 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 7, 2018, 3:35 PM
*
* \file transcend.cpp
* \brief Transcend's tests
*/
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "supplemental/docutils.h"
#include <gtest/gtest.h>
using namespace xreate;
using namespace std;
TEST(Transcend, Parse1) {
std::string script =
R"Code(
)Code";
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(std::move(script)));
std::string scriptTranscend =
R"Code(
test1((1)).
test2((1, 2)).
+ test3(1, "a").
)Code";
man->transcend->addRawScript(move(scriptTranscend));
man->analyse();
StaticModel solution = man->transcend->query("test1");
Gringo::Symbol symbTest1 = solution.begin()->second;
auto answer1 = man->transcend->parse<list<int>>(symbTest1);
ASSERT_EQ(1, get<0>(answer1).size());
solution = man->transcend->query("test2");
Gringo::Symbol symbTest2 = solution.begin()->second;
auto answer2 = get<0>(man->transcend->parse<list<int>>(symbTest2));
ASSERT_EQ(2, answer2.size());
+
+ typedef std::tuple<int, string> Predicate3;
+ solution = man->transcend->query("test3");
+ Gringo::Symbol symbTest3 = solution.begin()->second;
+ auto answer3a = get<0>(man->transcend->parse(schemeT<Predicate3>(), symbTest3));
+ auto answer3b = get<1>(man->transcend->parse(schemeT<Predicate3>(), symbTest3));
+ ASSERT_EQ(1, answer3a);
+ ASSERT_STREQ("a", answer3b.c_str());
}
TEST(Transcend, Doc_Expressions1) {
string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Expressions1");
XreateManager* man = XreateManager::prepare(move(code));
man->run();
delete man;
ASSERT_TRUE(true);
}
TEST(Transcend, Doc_SlaveTypes1){
string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Codeblocks1");
XreateManager::prepare(move(code));
ASSERT_TRUE(true);
}
TEST(Transcend, Doc_Codeblocks1) {
string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Codeblocks1");
XreateManager::prepare(move(code));
ASSERT_TRUE(true);
}
TEST(Transcend, Doc_Diagnostics1) {
string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Diagnostics1");
string scriptTranscend = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Diagnostics1_Rules");
string scriptSupport =
R"Code(
scope_func_dict(S, Fn):-
cfa_parent(S, function(Fn)).
scope_func_dict(S1, Fn):-
cfa_parent(S1, scope(S2));
scope_func_dict(S2, Fn).
)Code";
auto man = XreateManager::prepare(move(code));
man->transcend->addRawScript(move(scriptTranscend));
man->transcend->addRawScript(move(scriptSupport));
testing::internal::CaptureStdout();
man->run();
delete man;
std::string outputActual = testing::internal::GetCapturedStdout();
std::cout << outputActual << std::endl;
string outputExpected = "warning(\"Visibility violation\",\"test\",\"sum\")";
ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
}
\ No newline at end of file
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 110d315..5592981 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,248 +1,311 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "gtest/gtest.h"
#include "xreatemanager.h"
#include "llvmlayer.h"
#include "main/Parser.h"
#include "transcendlayer.h"
#include "analysis/typeinference.h"
-#include "analysis/interpretation.h"
+#include "analysis/utils.h"
using namespace std;
using namespace xreate;
using namespace xreate::grammar::main;
TEST(Types, DependantTypes1) {
string&& code = "XmlNode = type {\n"
" tag:: string,\n"
" attrs:: [string], \n"
" content:: string\n"
"}.\n";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeXmlNode = program->root->findType("XmlNode");
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeXmlNode->__operator);
+ ASSERT_EQ(TypeOperator::RECORD, typeXmlNode->__operator);
ASSERT_EQ(3, typeXmlNode->__operands.size());
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
- ASSERT_EQ(TypeOperator::LIST_ARRAY, typeXmlNode->__operands.at(1).__operator);
+ ASSERT_EQ(TypeOperator::ARRAY, typeXmlNode->__operands.at(1).__operator);
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(2).__value);
}
TEST(Types, ast_ParameterizedTypes_FeatureTypeIndex_1) {
string&& code = "XmlNode = type {\n"
" tag:: string,\n"
" attrs:: [string],\n"
" content:: string\n"
"}.\n"
""
"Template = type(Leaf) {Leaf, [Leaf[\"content\"]]}."
"Concrete = type Template(XmlNode).";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeConcrete->__operator);
+ ASSERT_EQ(TypeOperator::RECORD, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeConcrete->__operands.at(0).__operator);
+ ASSERT_EQ(TypeOperator::RECORD, typeConcrete->__operands.at(0).__operator);
- ASSERT_EQ(TypeOperator::LIST_ARRAY, typeConcrete->__operands.at(1).__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 {\n"
" tag:: string,\n"
" attrs:: [string],\n"
" content:: string\n"
"}.\n"
""
"Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
"Concrete = type Tree(XmlNode).";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeConcrete->__operator);
+ ASSERT_EQ(TypeOperator::RECORD, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeConcrete->__operands.at(0).__operator);
+ ASSERT_EQ(TypeOperator::RECORD, typeConcrete->__operands.at(0).__operator);
- ASSERT_EQ(TypeOperator::LIST_ARRAY, typeConcrete->__operands.at(1).__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);
+// ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
+// ASSERT_EQ(typeConcrete->linkId, typeLink.linkId);
}
TEST(Types, TreeType1LLvm) {
string&& code = "XmlNode = type {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
"Concrete = type Tree(XmlNode).";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
TEST(Types, ArrayOfExternal1) {
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST* ast = parser.root->finalize();
CodeScope* body = ast->findFunction("test")->getEntryScope();
const ExpandedType& t2 = ast->getType(body->getDefinition(body->getSymbol("childrenRaw")));
- EXPECT_EQ(t2->__operator, TypeOperator::LIST_ARRAY);
+ EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
}
TEST(Types, ExternType1) {
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST* ast = parser.root->finalize();
CodeScope* body = ast->findFunction("test")->getEntryScope();
const ExpandedType& t2 = ast->getType(body->getDefinition(body->getSymbol("tree")));
- EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
+ EXPECT_EQ(t2->__operator, TypeOperator::ALIAS);
}
TEST(Types, ast_VariantType1) {
string&& code =
" colors = type variant {RED, BLUE, GREEN}.\n"
" test = function:: colors; entry {GREEN()}";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typ = program->root->findType("colors");
EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody();
EXPECT_EQ(Operator::VARIANT, eRed.op);
const ExpandedType& typ2 = program->root->getType(eRed);
EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
}
TEST(Types, full_VariantType_Switch1) {
string&& code =
"colors = type variant{RED, BLUE, GREEN}. \n"
" test = function:: colors {GREEN()} \n"
"main = function:: int; entry { \n"
" switch(test()):: int \n"
" case (GREEN()) {0} \n"
" case default {1} \n"
"}";
XreateManager* man = XreateManager::prepare(move(code));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(0, main());
}
TEST(Types, ast_VariantType2) {
std::string script =
R"Code(
Annotation = type
variant {
- Num:: int,
- String:: string,
- Func:: {name::string, arguments::[Expression]}
+ Num(int),
+ String(string),
+ Func(name::string, arguments::[Expression])
}.
)Code";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(script)));
ExpandedType typ = program->root->findType("Annotation");
ASSERT_EQ(3, typ.get().fields.size());
}
TEST(Types, SlaveTypes_UnwrapSlaveType1) {
auto man = details::tier1::XreateManager::prepare(R"Code(
AtomNumT = type slave atomNumT.
AtomStrT = type slave atomStrT.
CmpndIntStrT = type slave cmpndIntStrT.
VariantT = type slave variantT.
VariantComplicatedT = type slave variantComplicatedT.
)Code");
man->transcend->addRawScript(R"RAW(
atomNumT(5). atomNumT(8).
atomStrT("a"). atomStrT("b").
cmpndIntStrT(1, "a").
cmpndIntStrT(2, "b").
variantT(first).
variantT(second).
variantT(third).
variantComplicatedT(first(1, "a")).
variantComplicatedT(second("b")).
)RAW");
man->analyse();
ExpandedType AtomNumT = man->root->findType("AtomNumT");
ASSERT_EQ(AtomNumT->__operator, TypeOperator::SLAVE);
- ExpandedType ContentAtomNumT = interpretation::dereferenceSlaveType(AtomNumT, man->transcend);
- ASSERT_EQ(TypePrimitive::Num, ContentAtomNumT->__value);
+ ExpandedType ContentAtomNumT = analysis::dereferenceSlaveType(AtomNumT, man->transcend);
+ ASSERT_EQ(TypePrimitive::Int, ContentAtomNumT->__value);
ExpandedType AtomStrT = man->root->findType("AtomStrT");
- ExpandedType ContentAtomStrT = interpretation::dereferenceSlaveType(AtomStrT,
+ ExpandedType ContentAtomStrT = analysis::dereferenceSlaveType(AtomStrT,
man->transcend);
ASSERT_EQ(TypePrimitive::String, ContentAtomStrT->__value);
ExpandedType CmpndIntStrT = man->root->findType("CmpndIntStrT");
- ExpandedType ContentCmpndIntStrT = interpretation::dereferenceSlaveType(CmpndIntStrT,
+ ExpandedType ContentCmpndIntStrT = analysis::dereferenceSlaveType(CmpndIntStrT,
man->transcend);
- ASSERT_EQ(TypeOperator::LIST_RECORD, ContentCmpndIntStrT->__operator);
+ ASSERT_EQ(TypeOperator::RECORD, ContentCmpndIntStrT->__operator);
ASSERT_EQ(2, ContentCmpndIntStrT->__operands.size());
ExpandedType VariantT = man->root->findType("VariantT");
- ExpandedType ContentVariantT = interpretation::dereferenceSlaveType(VariantT,
+ ExpandedType ContentVariantT = analysis::dereferenceSlaveType(VariantT,
man->transcend);
ASSERT_EQ(TypeOperator::VARIANT, ContentVariantT->__operator);
ASSERT_EQ(3, ContentVariantT->fields.size());
ExpandedType VariantComplicatedT = man->root->findType("VariantComplicatedT");
- ExpandedType ContentVariantComplicatedT = interpretation::dereferenceSlaveType(VariantComplicatedT,
+ ExpandedType ContentVariantComplicatedT = analysis::dereferenceSlaveType(VariantComplicatedT,
man->transcend);
ASSERT_EQ(TypeOperator::VARIANT, ContentVariantComplicatedT->__operator);
ASSERT_EQ(2, ContentVariantComplicatedT->fields.size());
ASSERT_EQ(2, ContentVariantComplicatedT->__operands.at(0).__operands.size());
}
TEST(Types, IndexNumber_1)
{
string&& code =
R"CODE(
Tuple = type {string, int}.
Int = type Tuple[1].
)CODE";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeInt = program->root->findType("Int");
}
+
+TEST(Types, RecursiveTypes_1){
+string&& code =
+R"CODE(
+ Node = type {
+ data:: int,
+ next:: ref(Node)
+ }
+)CODE";
+ std::string outputExpected = "{ i32, %Node* }";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typNode = program->root->findType("Node");
+ llvm::Type* typNodeRaw = program->llvm->toLLVMType(typNode);
+
+ std::string outputActual;
+ llvm::raw_string_ostream os(outputActual);
+ typNodeRaw->print(os);
+ os.flush();
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Types, RecursiveTypes_2){
+ string&& code =
+ R"CODE(
+ Tree = type(NodeData) variant {
+ LEAF(data:: NodeData),
+ GROUP(nodes:: [ref(Tree(NodeData))])
+ }
+
+ Guard = type variant {
+ a, b
+ }.
+
+ DecisionTree = type Tree(Guard).
+)CODE";
+
+ std::string outputExpected = "{ i8, { { i8 } } ";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typNode = program->root->findType("DecisionTree");
+ llvm::Type* typNodeRaw = program->llvm->toLLVMType(typNode);
+
+ std::string outputActual;
+ llvm::raw_string_ostream os(outputActual);
+ typNodeRaw->print(os);
+ os.flush();
+ cout << outputActual << endl;
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Types, NestedList1){
+ string code = R"(
+test = function:: int; entry()
+{
+ x = {a = {b = 3}}:: {a:: {b:: int}}.
+ x["a", "b"]
+}
+)";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ program->run();
+}
\ No newline at end of file
diff --git a/documentation-api/diagrams/interpretation.graphml b/documentation-api/diagrams/interpretation.graphml
index 4d43541..3460b34 100644
--- a/documentation-api/diagrams/interpretation.graphml
+++ b/documentation-api/diagrams/interpretation.graphml
@@ -1,502 +1,520 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
- <!--Created by yEd 3.18.1-->
+ <!--Created by yEd 3.19.1.1-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0" xml:space="preserve"/>
<node id="n0" yfiles.foldertype="group">
<data key="d6">
<y:TableNode configuration="YED_TABLE_NODE">
- <y:Geometry height="662.9150205991655" width="823.2444507237494" x="-754.2385841007069" y="-87.55439715328473"/>
+ <y:Geometry height="662.9150205991655" width="823.2444507237495" x="-613.9130668593276" y="-53.73922473949166"/>
<y:Fill color="#ECF5FF" color2="#0042F440" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="33.1943359375" x="395.0250573931247" xml:space="preserve" y="4.0">I12n</y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.677734375" x="134.49991149468747" xml:space="preserve" y="33.0">Pass<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="141.408203125" x="490.7569024815622" xml:space="preserve" y="33.0">Compilation/Interpretation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="33.2236328125" x="395.01040895562477" xml:space="preserve" y="4.0">I12n</y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.484375" x="134.59659118218747" xml:space="preserve" y="33.0">Pass<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="145.7265625" x="488.59772279406224" xml:space="preserve" y="33.0">Compilation/Interpretation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="yed.table.section.color" value="#7192b2"/>
<y:Property class="java.lang.Double" name="yed.table.header.height" value="24.0"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.main" value="#c4d7ed"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.alternating" value="#abc8e2"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.alternating" value="#abc8e2"/>
<y:Property class="java.lang.String" name="yed.table.lane.style" value="lane.style.columns"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.main" value="#c4d7ed"/>
</y:StyleProperties>
<y:State autoResize="true" closed="false" closedHeight="80.0" closedWidth="100.0"/>
<y:Insets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
- <y:BorderInsets bottom="17" bottomF="17.041583099165564" left="0" leftF="0.0" right="40" rightF="40.0" top="19" topF="18.75"/>
+ <y:BorderInsets bottom="66" bottomF="65.83813482330345" left="40" leftF="40.06064116379309" right="35" rightF="35.08575931749965" top="19" topF="18.75"/>
<y:Table autoResizeTable="true" defaultColumnWidth="120.0" defaultMinimumColumnWidth="80.0" defaultMinimumRowHeight="50.0" defaultRowHeight="80.0">
<y:DefaultColumnInsets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
<y:DefaultRowInsets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
<y:Insets bottom="0.0" left="0.0" right="0.0" top="30.0"/>
<y:Columns>
<y:Column id="column_0" minimumWidth="80.0" width="299.67755736437493">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
- <y:Column id="column_1" minimumWidth="80.0" width="523.5668933593745">
+ <y:Column id="column_1" minimumWidth="80.0" width="523.5668933593746">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
</y:Columns>
<y:Rows>
<y:Row height="608.9150205991655" id="row_0" minimumHeight="50.0">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
</y:Row>
</y:Rows>
</y:Table>
</y:TableNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n0">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="57.5703125" width="97.78271484375" x="-754.2385841007069" y="185.41044659671527"/>
+ <y:Geometry height="57.5703125" width="64.9462890625" x="-416.1189918997372" y="239.01077526050838"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.78271484375" x="5.0" xml:space="preserve" y="3.0">Function
-Interpretation
-Data<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="54.9462890625" x="5.0" xml:space="preserve" y="3.0">I12n
+Function
+Spec<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n1">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="57.5703125" width="97.78271484375" x="-589.0385841007069" y="196.0104465967154"/>
+ <y:Geometry height="57.5703125" width="97.78271484375" x="-566.5613427213964" y="267.04046276050826"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.78271484375" x="5.0" xml:space="preserve" y="3.0">Function
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="84.1708984375" x="6.805908203125" xml:space="preserve" y="3.0">Function
Interpretation
Helper<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n2">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="42.17724609375" x="-559.655849725707" y="443.7121653467152"/>
+ <y:Geometry height="43.046875" width="42.17724609375" x="-497.5889531739829" y="432.64046276050817"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="32.17724609375" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.787109375" x="5.695068359375" xml:space="preserve" y="3.0">I12n
Data<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n3">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="152.68359375" x="-700.889023553832" y="320.79560284671516"/>
+ <y:Geometry height="30.0" width="152.68359375" x="-560.5635063124528" y="354.61077526050826"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="142.68359375" x="5.0" xml:space="preserve" y="3.0">InterpretationOperator<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="135.701171875" x="8.4912109375" xml:space="preserve" y="3.0">InterpretationOperator<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n4">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="128.1435546875" x="-643.4190040225819" y="95.19560284671527"/>
+ <y:Geometry height="30.0" width="128.1435546875" x="-503.09348678120267" y="129.01077526050835"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="118.1435546875" x="5.0" xml:space="preserve" y="3.0">InterpretationPass<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="112.9130859375" x="7.615234375" xml:space="preserve" y="3.0">InterpretationPass<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n5">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="51.57177734375" x="-654.333115350707" y="444.27216534671516"/>
+ <y:Geometry height="43.046875" width="51.57177734375" x="-573.8524256955345" y="432.64046276050817"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="41.57177734375" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="38.56298828125" x="6.50439453125" xml:space="preserve" y="3.0">I12n
Query<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n6">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="81.16455078125" x="-683.129502069457" y="515.2721653467152"/>
+ <y:Geometry height="43.046875" width="81.16455078125" x="-573.8524256955345" y="500.2907860363704"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="71.16455078125" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="66.5625" x="7.301025390625" xml:space="preserve" y="3.0">I12n
Resolution<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n7">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="47.97265625" x="-606.3335548038319" y="-14.804397153284725"/>
+ <y:Geometry height="30.0" width="47.97265625" x="-466.0080375624526" y="19.01077526050834"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="37.97265625" x="5.0" xml:space="preserve" y="3.0">IPass<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.5380859375" x="5.71728515625" xml:space="preserve" y="3.0">IPass<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n8">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="68.87548828125" x="-177.51684581945693" y="201.67466534671533"/>
+ <y:Geometry height="43.046875" width="68.87548828125" x="-112.83132857807772" y="237.0873377605085"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="58.87548828125" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="54.9462890625" x="6.964599609375" xml:space="preserve" y="3.0">I12n
Function<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n9">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="53.0126953125" x="-305.2454493350819" y="254.5046653467157"/>
+ <y:Geometry height="43.046875" width="53.0126953125" x="-240.55993209370268" y="237.9584315105086"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="43.0126953125" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.4736328125" x="6.26953125" xml:space="preserve" y="3.0">I12n
Scope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n10">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="57.5703125" width="75.4072265625" x="-413.42271496008203" y="116.57294659671552"/>
+ <y:Geometry height="57.5703125" width="75.4072265625" x="-273.0971977187027" y="150.3881190105086"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.4072265625" x="5.0" xml:space="preserve" y="3.0">I12n
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="61.8271484375" x="6.7900390625" xml:space="preserve" y="3.0">I12n
Scope
Decorator<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n11">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="57.5703125" width="81.16455078125" x="-386.05137706945703" y="433.5729465967156"/>
+ <y:Geometry height="57.5703125" width="81.16455078125" x="-254.63585982807768" y="354.61077526050826"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="71.16455078125" x="5.0" xml:space="preserve" y="3.0">Intrinsic
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="67.44482421875" x="6.85986328125" xml:space="preserve" y="3.0">Intrinsic
Query
Instruction<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n12">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="73.95361328125" x="-56.61590831945688" y="194.27466534671566"/>
+ <y:Geometry height="43.046875" width="108.87841796875" x="65.36720657817222" y="324.21533776050865"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.95361328125" x="5.0" xml:space="preserve" y="3.0">PIF
-Signature<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.16064453125" x="10.85888671875" xml:space="preserve" y="3.0">PIFnSignature<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n13">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="68.87548828125" x="-175.980845819457" y="288.80266534671546"/>
+ <y:Geometry height="43.046875" width="77.1337890625" x="-115.42447896870277" y="324.21533776050865"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="58.87548828125" x="5.0" xml:space="preserve" y="3.0">PI
-Function<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="67.1337890625" x="5.0" xml:space="preserve" y="3.0">PIFunction<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n14">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="94.1455078125" x="-67.5918555850821" y="102.67466534671576"/>
+ <y:Geometry height="43.046875" width="108.87841796875" x="65.36720657817222" y="136.4898377605088"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="84.1455078125" x="5.0" xml:space="preserve" y="3.0">PI
-FunctionUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.87841796875" x="5.0" xml:space="preserve" y="3.0">PIBruteFunction<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n15">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="137.5126953125" x="-287.47544933508203" y="134.95810284671566"/>
+ <y:Geometry height="30.0" width="137.5126953125" x="-147.14993209370272" y="168.77327526050874"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="127.5126953125" x="5.0" xml:space="preserve" y="3.0">TargetInterpretation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="122.77734375" x="7.36767578125" xml:space="preserve" y="3.0">TargetInterpretation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n16">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="89.12451171875" x="-422.56135753820723" y="23.638102846715725"/>
+ <y:Geometry height="30.0" width="89.12451171875" x="-282.2358402968279" y="57.95825222675845"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="79.12451171875" x="5.0" xml:space="preserve" y="3.0">ICodeScope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="74.49072265625" x="7.31689453125" xml:space="preserve" y="3.0">ICodeScope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n17">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="53.72998046875" x="-259.08409191320703" y="49.95810284671555"/>
+ <y:Geometry height="30.0" width="53.72998046875" x="-105.25857467182772" y="57.95825222675845"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="43.72998046875" x="5.0" xml:space="preserve" y="3.0">Target<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="42.6064453125" x="5.561767578125" xml:space="preserve" y="3.0">Target<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n18">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="97.75732421875" x="-68.75145759570745" y="20.64805677921504"/>
+ <y:Geometry height="30.0" width="108.87841796875" x="65.36720657817222" y="57.95825222675845"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.75732421875" x="5.0" xml:space="preserve" y="3.0">IFunctionUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="90.48681640625" x="9.19580078125" xml:space="preserve" y="3.0">IBruteFunction<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
</graph>
</node>
<node id="n1">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLNoteNode>
<y:Geometry height="41.19999999999999" width="114.701171875" x="-845.3592068797651" y="-83.53882750532699"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#FF0000" verticalTextPosition="bottom" visible="true" width="65.998046875" x="24.3515625" xml:space="preserve" y="11.896874999999994">Unfinished<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#FF0000" verticalTextPosition="bottom" visible="true" width="62.154296875" x="26.2734375" xml:space="preserve" y="11.568749999999994">Unfinished<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
</y:UMLNoteNode>
</data>
</node>
<edge id="n0::e0" source="n0::n13" target="n0::n8">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e1" source="n0::n15" target="n0::n17">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="-232.21910167883203" y="149.95810284671555"/>
- </y:Path>
- <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+ <y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e2" source="n0::n10" target="n0::n16">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
- <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e3" source="n0::n14" target="n0::n18">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
- <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e4" source="n0::n10" target="n0::n15">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e5" source="n0::n9" target="n0::n11">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e6" source="n0::n15" target="n0::n8">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e7" source="n0::n8" target="n0::n9">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
- <edge id="n0::e8" source="n0::n14" target="n0::n12">
+ <edge id="n0::e8" source="n0::n13" target="n0::n12">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+ <y:Path sx="12.491007928831834" sy="0.3207096532845526" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e9" source="n0::n4" target="n0::n7">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="-579.3472266788319" y="0.19560284671527484"/>
- </y:Path>
+ <y:Path sx="0.0" sy="0.0" tx="3.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e10" source="n0::n4" target="n0::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
+ <edge id="n0::e11" source="n0::n13" target="n0::n14">
+ <data key="d8" xml:space="preserve"/>
+ <data key="d10">
+ <y:PolyLineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+ <y:Point x="26.2348028017239" y="345.73877526050865"/>
+ <y:Point x="26.2348028017239" y="158.0132752605088"/>
+ </y:Path>
+ <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:Arrows source="diamond" target="none"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e12" source="n0::n13" target="n0::n0">
+ <data key="d8" xml:space="preserve"/>
+ <data key="d10">
+ <y:PolyLineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+ <y:LineStyle color="#000000" type="dashed" width="1.0"/>
+ <y:Arrows source="none" target="plain"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>
diff --git a/documentation-api/diagrams/latex.graphml b/documentation-api/diagrams/latex.graphml
index c537821..a7306de 100644
--- a/documentation-api/diagrams/latex.graphml
+++ b/documentation-api/diagrams/latex.graphml
@@ -1,819 +1,819 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
- <!--Created by yEd 3.18.1-->
+ <!--Created by yEd 3.19.1.1-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0" xml:space="preserve"/>
<node id="n0" yfiles.foldertype="group">
<data key="d6">
<y:TableNode configuration="YED_TABLE_NODE">
<y:Geometry height="301.2117579823405" width="799.186140432126" x="196.79155019287532" y="-192.46513398234035"/>
<y:Fill color="#ECF5FF" color2="#0042F440" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.6943359375" x="379.245902247313" xml:space="preserve" y="4.0">Latex</y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="67.36328125" x="136.88742959106293" xml:space="preserve" y="33.0">Compilation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="60.6953125" x="652.2944841821259" xml:space="preserve" y="33.0">Transcend<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="74.7109375" x="416.26267168212576" xml:space="preserve" y="33.0">Interpretation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_2" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.54052734375" x="379.322806544188" xml:space="preserve" y="4.0">Latex</y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="68.59375" x="136.27219521606293" xml:space="preserve" y="33.0">Compilation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="60.61328125" x="652.3354998071259" xml:space="preserve" y="33.0">Transcend<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.181640625" x="415.52732011962576" xml:space="preserve" y="33.0">Interpretation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_2" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="yed.table.section.color" value="#7192b2"/>
<y:Property class="java.lang.Double" name="yed.table.header.height" value="24.0"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.main" value="#c4d7ed"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.alternating" value="#abc8e2"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.alternating" value="#abc8e2"/>
<y:Property class="java.lang.String" name="yed.table.lane.style" value="lane.style.columns"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.main" value="#c4d7ed"/>
</y:StyleProperties>
<y:State autoResize="true" closed="false" closedHeight="80.0" closedWidth="100.0"/>
<y:Insets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
- <y:BorderInsets bottom="33" bottomF="33.42941839334418" left="0" leftF="0.0" right="106" rightF="106.4960000000001" top="0" topF="0.0"/>
+ <y:BorderInsets bottom="33" bottomF="33.42941839334418" left="0" leftF="0.0" right="62" rightF="61.58997832275122" top="0" topF="0.0"/>
<y:Table autoResizeTable="true" defaultColumnWidth="120.0" defaultMinimumColumnWidth="80.0" defaultMinimumRowHeight="50.0" defaultRowHeight="80.0">
<y:DefaultColumnInsets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
<y:DefaultRowInsets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
<y:Insets bottom="0.0" left="0.0" right="0.0" top="30.0"/>
<y:Columns>
<y:Column id="column_0" minimumWidth="80.0" width="341.13814043212585">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
<y:Column id="column_2" minimumWidth="80.0" width="224.95999999999992">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
<y:Column id="column_1" minimumWidth="80.0" width="233.0880000000002">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
</y:Columns>
<y:Rows>
<y:Row height="247.2117579823405" id="row_0" minimumHeight="50.0">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
</y:Row>
</y:Rows>
</y:Table>
</y:TableNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n0">
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="43.046875" width="94.88818359375" x="205.3961849585001" y="25.265718750000076"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="84.88818359375" x="5.0" xml:space="preserve" y="3.0">ExtraArgs
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="79.638671875" x="7.624755859375" xml:space="preserve" y="3.0">ExtraArgs
FnInvocation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n1">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="57.5703125" width="86.9599609375" x="209.34429628662508" y="-76.87315624999997"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.9599609375" x="5.0" xml:space="preserve" y="3.0">Latex
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="72.21826171875" x="7.370849609375" xml:space="preserve" y="3.0">Latex
BruteScope
Dec<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n2">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="30.0" width="114.39453125" x="196.79155019287532" y="-138.46513398234035"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="104.39453125" x="5.0" xml:space="preserve" y="3.0">ICodeScopeUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.16748046875" x="8.113525390625" xml:space="preserve" y="3.0">ICodeScopeUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n3">
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="57.5703125" width="102.82275390625" x="350.50089980225005" y="-77.20915624999992"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="92.82275390625" x="5.0" xml:space="preserve" y="3.0">Latex
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="86.69091796875" x="8.06591796875" xml:space="preserve" y="3.0">Latex
BruteFunction
Dec<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n4">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="97.75732421875" x="351.27775419800065" y="-137.1598241279998"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.75732421875" x="5.0" xml:space="preserve" y="3.0">IFunctionUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="82.4189453125" x="7.669189453125" xml:space="preserve" y="3.0">IFunctionUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n5">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="30.0" width="128.12451171875" x="586.6580208960003" y="-126.27999999999997"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="118.12451171875" x="5.0" xml:space="preserve" y="3.0">getSubjectDomain<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="111.783203125" x="8.170654296875" xml:space="preserve" y="3.0">getSubjectDomain<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n6">
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="51.57177734375" x="836.6303880835001" y="-76.30628124999996"/>
+ <y:Geometry height="83.65160969387753" width="97.75732421875" x="836.6303880835001" y="-76.30628124999996"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="41.57177734375" x="5.0" xml:space="preserve" y="3.0">Latex
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="38.56298828125" x="29.59716796875" xml:space="preserve" y="3.0">Latex
Query<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
- <y:MethodLabel xml:space="preserve"/>
+ <y:MethodLabel xml:space="preserve">getFnDemand</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n7">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="55.18359375" x="834.2980968750012" y="-135.99964825599963"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="45.18359375" x="5.0" xml:space="preserve" y="3.0">IQuery<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="42.35888671875" x="6.412353515625" xml:space="preserve" y="3.0">IQuery<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n8">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="30.0" width="114.4072265625" x="596.3966634741248" y="-59.25599999999994"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="104.4072265625" x="5.0" xml:space="preserve" y="3.0">collapseColumn<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.1611328125" x="8.123046875" xml:space="preserve" y="3.0">collapseColumn<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n9">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="46.677734375" x="773.0534095678752" y="-116.655824128"/>
<y:Fill color="#00FFFF" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.677734375" x="5.0" xml:space="preserve" y="-0.40625">Latex
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="34.978515625" x="5.849609375" xml:space="preserve" y="-1.0625">Latex
Query<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="star6"/>
</y:ShapeNode>
</data>
</node>
<node id="n0::n10">
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="57.5703125" width="86.48447265624998" x="608.4554275590741" y="17.74689310665596"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="74.08447265625" x="6.199999999999989" xml:space="preserve" y="3.0">represent
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="49.703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="68.48583984375" x="8.999316406249989" xml:space="preserve" y="3.0">represent
Trans
Expression<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
</graph>
</node>
<node id="n1" yfiles.foldertype="group">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
- <y:Geometry height="629.5999999999996" width="839.7171093750001" x="181.1570562500006" y="172.33863125000016"/>
+ <y:Geometry height="630.4203124999996" width="839.7171093750001" x="181.1570562500006" y="171.51831875000016"/>
<y:Fill color="#CAECFF80" transparent="false"/>
<y:BorderStyle color="#666699" type="dotted" width="1.0"/>
- <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#99CCFF" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="839.7171093750001" x="0.0" xml:space="preserve" y="0.0">Latex script</y:NodeLabel>
+ <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#99CCFF" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="839.7171093750001" x="0.0" xml:space="preserve" y="0.0">Latex script</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:NodeBounds considerNodeLabelSize="true"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="30" bottomF="30.0" left="143" leftF="143.02587890625" right="85" rightF="85.42316406250006" top="61" topF="60.842187499999795"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="102.0" x="181.1570562500006" y="172.33863125000016"/>
<y:Fill color="#CAECFF80" transparent="false"/>
<y:BorderStyle color="#666699" type="dotted" width="1.0"/>
- <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#99CCFF" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="102.0" x="0.0" xml:space="preserve" y="0.0">Latex script</y:NodeLabel>
+ <y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#99CCFF" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="102.0" x="0.0" xml:space="preserve" y="0.0">Latex script</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="102.0" innerGraphDisplayEnabled="false"/>
<y:NodeBounds considerNodeLabelSize="true"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n1:">
<node id="n1::n0" yfiles.foldertype="group">
<data key="d6">
<y:TableNode configuration="com.yworks.bpmn.Pool">
<y:Geometry height="507.9999999999998" width="601.26806640625" x="329.1829351562506" y="258.93863124999996"/>
<y:Fill color="#FFF2BC" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="l" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.6943359375" x="4.0" xml:space="preserve" y="233.6528320312499">Latex</y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.0234375" x="33.0" xml:space="preserve" y="89.50915527343773">Output<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_0" inside="true"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.361328125" x="33.0" xml:space="preserve" y="266.50952148437545">Processing<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_1" inside="true"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.689453125" x="33.0" xml:space="preserve" y="435.8245849609376">Input<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_2" inside="true"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="l" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.54052734375" x="4.0" xml:space="preserve" y="233.7297363281249">Latex</y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="40.076171875" x="33.0" xml:space="preserve" y="89.48278808593773">Output<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_0" inside="true"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.794921875" x="33.0" xml:space="preserve" y="266.29272460937545">Processing<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_1" inside="true"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" rotationAngle="270.0" textColor="#000000" verticalTextPosition="bottom" visible="true" width="31.169921875" x="33.0" xml:space="preserve" y="435.5843505859376">Input<y:LabelModel><y:RowNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_2" inside="true"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property name="y.view.tabular.TableNodePainter.ALTERNATE_ROW_STYLE">
<y:SimpleStyle fillColor="#474A4340" lineColor="#000000" lineType="line" lineWidth="1.0"/>
</y:Property>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property name="y.view.tabular.TableNodePainter.ALTERNATE_COLUMN_SELECTION_STYLE">
<y:SimpleStyle fillColor="#474A4380" lineColor="#000000" lineType="line" lineWidth="3.0"/>
</y:Property>
<y:Property name="y.view.tabular.TableNodePainter.ALTERNATE_ROW_SELECTION_STYLE">
<y:SimpleStyle fillColor="#474A4380" lineColor="#000000" lineType="line" lineWidth="3.0"/>
</y:Property>
<y:Property class="java.awt.Color" name="POOL_LANE_COLOR_ALTERNATING" value="#ffffff"/>
<y:Property class="java.awt.Color" name="POOL_LANE_COLOR_MAIN" value="#ffffcc"/>
<y:Property class="java.lang.String" name="POOL_LANE_STYLE" value="LANE_STYLE_ROWS"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="POOL_TYPE_LANE"/>
<y:Property name="y.view.tabular.TableNodePainter.ALTERNATE_COLUMN_STYLE">
<y:SimpleStyle fillColor="#474A4340" lineColor="#000000" lineType="line" lineWidth="1.0"/>
</y:Property>
</y:StyleProperties>
<y:State autoResize="true" closed="false" closedHeight="80.0" closedWidth="100.0"/>
<y:Insets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
<y:BorderInsets bottom="25" bottomF="25.499999999999886" left="9" leftF="9.34423828125" right="24" rightF="23.56306093749936" top="5" topF="4.938631249999958"/>
<y:Table autoResizeTable="true" defaultColumnWidth="360.0" defaultMinimumColumnWidth="30.0" defaultMinimumRowHeight="30.0" defaultRowHeight="107.0">
<y:DefaultColumnInsets bottom="3.0" left="3.0" right="3.0" top="20.0"/>
<y:DefaultRowInsets bottom="3.0" left="20.0" right="3.0" top="3.0"/>
<y:Insets bottom="0.0" left="30.0" right="0.0" top="0.0"/>
<y:Columns>
<y:Column id="column_0" minimumWidth="30.0" width="548.26806640625">
<y:Insets bottom="3.0" left="3.0" right="3.0" top="20.0"/>
</y:Column>
</y:Columns>
<y:Rows>
<y:Row height="179.04174804687545" id="row_0" minimumHeight="50.703125">
<y:Insets bottom="3.0" left="20.0" right="3.0" top="3.0"/>
</y:Row>
<y:Row height="198.296875" id="row_1" minimumHeight="50.703125">
<y:Insets bottom="3.0" left="20.0" right="3.0" top="3.0"/>
</y:Row>
<y:Row height="107.66137695312432" id="row_2" minimumHeight="50.703125">
<y:Insets bottom="3.0" left="20.0" right="3.0" top="3.0"/>
</y:Row>
</y:Rows>
</y:Table>
</y:TableNode>
</data>
<graph edgedefault="directed" id="n1::n0:">
<node id="n1::n0::n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Artifact.withShadow">
<y:Geometry height="30.0" width="64.021484375" x="543.7902309604715" y="695.9386312499998"/>
<y:Fill color="#FFFFFFE6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="54.021484375" x="5.0" xml:space="preserve" y="-0.40625">Demand
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="54.953125" x="4.5341796875" xml:space="preserve" y="-1.0625">Demand
upstream<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ARTIFACT_TYPE_ANNOTATION"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n1">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="55.0" width="122.08203125" x="388.5271734375006" y="683.4386312499998"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="118.08203125" x="2.0" xml:space="preserve" y="18.796875">latex_scope_demand<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="116.51171875" x="2.78515625" xml:space="preserve" y="18.46875">latex_scope_demand<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n2">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="150.078125" x="620.8816656250006" y="695.9386312499998"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="140.078125" x="5.0" xml:space="preserve" y="6.296875">latex_registered_subjects<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="139.462890625" x="5.3076171875" xml:space="preserve" y="5.96875">latex_registered_subjects<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n3">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="55.0" width="110.7265625" x="394.2049078125006" y="526.9386312499997"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.7265625" x="5.0" xml:space="preserve" y="18.796875">scope_demand(1)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.439453125" x="5.1435546875" xml:space="preserve" y="18.46875">scope_demand(1)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n4">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="74.046875" x="412.5447515625006" y="395.93863124999996"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="64.046875" x="5.0" xml:space="preserve" y="6.296875">fn_demand<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.7890625" x="5.12890625" xml:space="preserve" y="5.96875">fn_demand<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n5">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="58.02734375" x="556.4070562500006" y="395.93863124999996"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="48.02734375" x="5.0" xml:space="preserve" y="6.296875">decision<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="48.912109375" x="4.5576171875" xml:space="preserve" y="5.96875">decision<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n6">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="110.7265625" x="530.0574468750006" y="539.4386312499997"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.7265625" x="5.0" xml:space="preserve" y="6.296875">scope_demand(2)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.439453125" x="5.1435546875" xml:space="preserve" y="5.96875">scope_demand(2)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n7">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="85.3671875" x="725.9371343750006" y="396.33863124999993"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="75.3671875" x="5.0" xml:space="preserve" y="6.296875">late(decision)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.931640625" x="4.2177734375" xml:space="preserve" y="5.96875">late(decision)<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n8">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="62.703125" x="737.2691656250006" y="539.4386312499997"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="52.703125" x="5.0" xml:space="preserve" y="6.296875">scope_fn<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="52.6328125" x="5.03515625" xml:space="preserve" y="5.96875">scope_fn<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n9">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="122.08203125" x="388.5271734375006" y="283.8772624999999"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="112.08203125" x="5.0" xml:space="preserve" y="6.296875">fn_demand_ordered<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="110.44140625" x="5.8203125" xml:space="preserve" y="5.96875">fn_demand_ordered<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n1::n0::n10">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
<y:Geometry height="30.0" width="83.99609375" x="819.8918468750012" y="539.8772624999995"/>
<y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" transparent="false"/>
<y:BorderStyle color="#123EA2" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="74.03125" x="4.982421875" xml:space="preserve" y="6.296875">latex_symbol<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="73.99609375" x="5.0" xml:space="preserve" y="5.96875">latex_symbol<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.line.color" value="#000000"/>
<y:Property class="com.yworks.yfiles.bpmn.view.TaskTypeEnum" name="com.yworks.bpmn.taskType" value="TASK_TYPE_ABSTRACT"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill2" value="#d4d4d4cc"/>
<y:Property class="java.awt.Color" name="com.yworks.bpmn.icon.fill" value="#ffffffe6"/>
<y:Property class="com.yworks.yfiles.bpmn.view.BPMNTypeEnum" name="com.yworks.bpmn.type" value="ACTIVITY_TYPE"/>
<y:Property class="com.yworks.yfiles.bpmn.view.ActivityTypeEnum" name="com.yworks.bpmn.activityType" value="ACTIVITY_TYPE_TASK"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
</graph>
</node>
</graph>
</node>
<edge id="n0::e0" source="n0::n1" target="n0::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e1" source="n0::n1" target="n0::n6">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="591.1324163073757" y="48.36017587200024"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="white_diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e2" source="n0::n3" target="n0::n6">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="663.3244163073757" y="-6.167824127999808"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="white_diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e3" source="n0::n3" target="n0::n5">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e4" source="n0::n1" target="n0::n5">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e5" source="n0::n5" target="n0::n8">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e6" source="n0::n1" target="n0::n2">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e7" source="n0::n3" target="n0::n4">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e8" source="n0::n6" target="n0::n7">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e9" source="n0::n9" target="n0::n6">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e10" source="n0::n1" target="n0::n10">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="29.599999999999966" sy="0.0" tx="0.0" ty="17.599999999999994">
<y:Point x="324.0976638871992" y="-46.26795064334408"/>
<y:Point x="324.8242767553751" y="63.33204935665589"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::e0" source="n1::n0" target="n1::n0::n5">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-13.01307826711736" sy="-170.1693115234376" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e0" source="n1::n0::n0" target="n1::n0::n1">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e1" source="n1::n0::n3" target="n1::n0::n1">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e2" source="n1::n0::n4" target="n1::n0::n3">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e3" source="n1::n0::n5" target="n1::n0::n4">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e4" source="n1::n0::n5" target="n1::n0::n2">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="695.9207281250006" y="411.93863124999996"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e5" source="n1::n0::n6" target="n1::n0::n4">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e6" source="n1::n0::n6" target="n1::n0::n5">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="crows_foot_one_mandatory" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e7" source="n1::n0::n7" target="n1::n0::n8">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::e1" source="n1::n0::n7" target="n1::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-139.5127241750008" ty="-154.9999999999999">
<y:Point x="768.6207281250006" y="357.93863124999996"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e8" source="n1::n0::n7" target="n1::n0::n2">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="13.0" ty="0.0">
<y:Point x="708.9207281250006" y="411.33863124999993"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e9" source="n1::n0::n9" target="n1::n0::n4">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-19.0" sy="0.0" tx="-19.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e10" source="n1::n0::n9" target="n1::n0::n7">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="19.0" ty="0.0">
<y:Point x="787.6207281250006" y="298.8772624999999"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n1::n0::e11" source="n1::n0::n4" target="n1::n0::n7">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-20.0" ty="0.0">
<y:Point x="460.0" y="410.93863124999996"/>
<y:Point x="460.0" y="357.0"/>
<y:Point x="748.6207281250006" y="357.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>
diff --git a/documentation-api/diagrams/polymorphism.graphml b/documentation-api/diagrams/polymorphism.graphml
index baa6ea4..38c38fe 100644
--- a/documentation-api/diagrams/polymorphism.graphml
+++ b/documentation-api/diagrams/polymorphism.graphml
@@ -1,338 +1,332 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
- <!--Created by yEd 3.18.1-->
+ <!--Created by yEd 3.19.1.1-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0" xml:space="preserve"/>
<node id="n0" yfiles.foldertype="group">
<data key="d6">
<y:TableNode configuration="YED_TABLE_NODE">
<y:Geometry height="326.7583807373044" width="528.9366308593751" x="109.517333984375" y="-3.768748753865964"/>
<y:Fill color="#ECF5FF" color2="#0042F440" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="21.578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.7822265625" x="214.07720214843755" xml:space="preserve" y="4.0">Polymorphism</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="68.59375" x="129.07144042968753" xml:space="preserve" y="33.0">Compilation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="60.61328125" x="397.5299902343751" xml:space="preserve" y="33.0">Transcend<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="yed.table.section.color" value="#7192b2"/>
<y:Property class="java.lang.Double" name="yed.table.header.height" value="24.0"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.main" value="#c4d7ed"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.alternating" value="#abc8e2"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.alternating" value="#abc8e2"/>
<y:Property class="java.lang.String" name="yed.table.lane.style" value="lane.style.columns"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.main" value="#c4d7ed"/>
</y:StyleProperties>
<y:State autoResize="true" closed="false" closedHeight="80.0" closedWidth="100.0"/>
<y:Insets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
- <y:BorderInsets bottom="65" bottomF="65.36000000000013" left="33" leftF="32.765380859375" right="58" rightF="58.16000000000008" top="0" topF="0.0"/>
+ <y:BorderInsets bottom="54" bottomF="54.48000000000013" left="33" leftF="32.765380859375" right="58" rightF="58.16000000000008" top="44" topF="43.54818176269575"/>
<y:Table autoResizeTable="true" defaultColumnWidth="120.0" defaultMinimumColumnWidth="80.0" defaultMinimumRowHeight="50.0" defaultRowHeight="80.0">
<y:DefaultColumnInsets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
<y:DefaultRowInsets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
<y:Insets bottom="0.0" left="0.0" right="0.0" top="30.0"/>
<y:Columns>
<y:Column id="column_0" minimumWidth="80.0" width="326.73663085937505">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
<y:Column id="column_1" minimumWidth="80.0" width="202.20000000000005">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
</y:Columns>
<y:Rows>
<y:Row height="272.7583807373044" id="row_0" minimumHeight="50.0">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
</y:Row>
</y:Rows>
</y:Table>
</y:TableNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n0">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="43.046875" width="81.89453125" x="498.3994335937501" y="202.8796319834383"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="67.67333984375" x="7.110595703125" xml:space="preserve" y="3.0">Polymorph
Query<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n1">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="55.18359375" x="503.0599023437501" y="50.231251246134036"/>
+ <y:Geometry height="30.0" width="55.18359375" x="511.7549023437501" y="95.02000000000001"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="42.35888671875" x="6.412353515625" xml:space="preserve" y="3.0">IQuery<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n2">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="66.453125" width="110.78271484375" x="281.9553417968751" y="191.1765069834383"/>
+ <y:Geometry height="97.81312500000001" width="110.78271484375" x="281.9553417968751" y="170.69650698343827"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="94.37158203125" x="8.20556640625" xml:space="preserve" y="3.0">Polymorph
CodeScopeUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">findFunction</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n3">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="114.39453125" x="272.2876367187501" y="50.259433008829774"/>
+ <y:Geometry height="30.0" width="114.39453125" x="270.8294335937501" y="93.77943300882978"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.16748046875" x="8.113525390625" xml:space="preserve" y="3.0">ICodeScopeUnit<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n4">
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="94.88818359375" x="145.90260742187508" y="202.8796319834383"/>
+ <y:Geometry height="43.046875" width="94.88818359375" x="145.90260742187508" y="198.07963198343828"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="34.46875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="79.638671875" x="7.624755859375" xml:space="preserve" y="3.0">Polymorph
FnInvocation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="41.52000000000004" width="47.135625000000005" x="448.5132954166678" y="147.56170500000025"/>
<y:Fill color="#CCFFCC" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="45.712890625" x="0.7113671875000023" xml:space="preserve" y="11.72875000000002">P.Query<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="star8"/>
</y:ShapeNode>
</data>
</node>
<node id="n0::n6">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="41.52000000000004" width="47.33984375" x="237.6044814583356" y="149.5634100000005"/>
+ <y:Geometry height="41.52000000000004" width="47.33984375" x="223.48958984375008" y="126.47796999613402"/>
<y:Fill color="#CCFFCC" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.0625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="34.287109375" x="6.5263671875" xml:space="preserve" y="11.72875000000002">PSCU<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="star8"/>
</y:ShapeNode>
</data>
</node>
<node id="n0::n7">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
- <y:Geometry height="30.0" width="93.4345703125" x="142.28271484375" y="51.5"/>
+ <y:Geometry height="30.0" width="93.4345703125" x="142.28271484375" y="95.02000000000001"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="83.4345703125" x="5.0" xml:space="preserve" y="3.0">IFnInvocation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
</graph>
</node>
<node id="n1">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="136.79541015625" x="125.60899414062504" y="437.6794330088297"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="120.64453125" x="8.075439453125" xml:space="preserve" y="3.0">InterpretationScope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n2">
<data key="d4" xml:space="preserve"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="163.525390625" x="112.64400390625002" y="362.43943300882967"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="144.30224609375" x="9.611572265625" xml:space="preserve" y="3.0">LateReasoningCompiler<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<edge id="n0::e0" source="n0::n2" target="n0::n3">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="328.0266992187501" y="217.73125124613404"/>
- </y:Path>
+ <y:Path sx="-9.319999999999993" sy="-22.351818237304258" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e1" source="n0::n0" target="n0::n1">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="534.0266992187501" y="65.23125124613404"/>
- </y:Path>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e2" source="n0::n2" target="n0::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e3" source="n0::n2" target="n0::n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e0" source="n2" target="n1">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n0::n4" target="n2">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n0::n4" target="n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e4" source="n0::n4" target="n0::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="367.8200000000001" y="296.7666666666667"/>
+ <y:Point x="193.34669921875008" y="296.7666666666667"/>
+ <y:Point x="539.34669921875" y="296.7666666666667"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e5" source="n0::n5" target="n0::n0">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e6" source="n0::n6" target="n0::n2">
<data key="d8" xml:space="preserve"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e7" source="n0::n4" target="n0::n7">
<data key="d8" xml:space="preserve"/>
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
- <y:Point x="189.0" y="224.4030694834383"/>
- </y:Path>
+ <y:Path sx="-4.346699218750075" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>
diff --git a/documentation/Concepts/interpretation.xml b/documentation/Concepts/interpretation.xml
index e5e6ec3..5a160ac 100644
--- a/documentation/Concepts/interpretation.xml
+++ b/documentation/Concepts/interpretation.xml
@@ -1,882 +1,882 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 26cy4nalqsw pu35zrt1aby9?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1abya?>Interpretation</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyb?>Interpretation is a compiler's mode
reserved to evaluate, expand and simplify parts of a given program based on
information available in this mode. On the other hand, Interpretation is a
middle man, or an intermediate level, between the Transcend and Brute
levels, as it facilitates communication between those by means of
interpreting data of respective layers. It can be further divided into Upper
and Lower Interpretations depending on the interaction with the layer we are
focused on at the moment.</para>
<remark><?xxe-sn 26stp2g6sxs p?><emphasis role="bold"><?xxe-sn 26stp2g6sxs q?>mode
whereby - как это перевести? - это режим с помощью которого xreate
интерпретирует? Авторский смысл: это режим(компилятора) В КОТОРОМ компилятор
интерпретирует. </emphasis></remark>
<remark><?xxe-sn 26stp2g6sxs 1?>Program: Речь идет о компьютерной программе,
или может приложении для смартфона, или алгоритме? Тогда лучше употребить
соответственно software ('piece of software') / app / algorithm. Вообще
"наши" компьютерные программы - это у них software, а не programs - -
<emphasis role="bold"><?xxe-sn 26stp2g6sxs 2?>ДА ТУТ СЛОВО PROGRAM ПОДХОДИТ,
особенно в контексте обработки программы с какимито целями, как здесь, чтоб
ее интерпретировать.</emphasis></remark>
<programlisting xml:id="Intr_1"><?xxe-sn 26cy4nalqsw pu35zrt1abyd?>name="tests/interpretation.cpp: Interpretation.Doc_Intr_1"
main= function:: int; entry
{
x= "a":: string.
y= if (x=="b"):: string; i12n(on)
{1} else {0}.
y
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abye?>In this example, the identifier
<code><?xxe-sn 26cy4nalqsw pu35zrt1abyf?>y</code> has an attached annotation
<code><?xxe-sn 26cy4nalqsw pu35zrt1abyg?>i12(on)</code> which indicates that
the compiler should use compile-time interpretation to evaluate
<code><?xxe-sn 26cy4nalqsw pu35zrt1abyh?>y</code>. Once the simplification
process is over, the function returns <code><?xxe-sn 26cy4nalqsw pu35zrt1abyi?>0</code>,
with neither memory allocations for the string variable <code><?xxe-sn 26cy4nalqsw pu35zrt1abyj?>x</code>
nor any computation at runtime.</para>
<remark><?xxe-sn 26stp2g6sxs 3?>Annotation - может лучше value или
parameter? - <emphasis role="bold"><?xxe-sn 26stp2g6sxs 4?>да Annotation
подходит</emphasis></remark>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyk?>There are two annotations reserved
to control the interpretation process:</para>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1abyl?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abym?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyn?><code><?xxe-sn 26cy4nalqsw pu35zrt1abyo?>i12n(on)</code>
Forces compiler to interpret the annotated expression, function, or
function argument. It yields error if the expression is impossible to
interpret.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abyp?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyq?><code><?xxe-sn 26cy4nalqsw pu35zrt1abyr?>i12n(off)</code>
Disables interpretation for the annotated expression.</para>
</listitem>
</itemizedlist>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1abys?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1abyt?>Eligible Expressions</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyu?>Currently the compiler is able to
interpret the following expressions:</para>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1abyv?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abyw?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyx?>Atomic instructions: numbers,
strings, identifiers.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abyy?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abyz?>Relational and logic
operators e.g. <code><?xxe-sn 26cy4nalqsw pu35zrt1abz0?>x==true</code>,
<code><?xxe-sn 26cy4nalqsw pu35zrt1abz1?>x!=0</code>.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abz2?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abz3?><code><?xxe-sn 26cy4nalqsw pu35zrt1abz4?>if</code>,
<code><?xxe-sn 26cy4nalqsw pu35zrt1abz5?>switch</code> statements.
[[#late-interpretation-or-e|Statement expansion]] allowed.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abz6?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abz7?>Loop statements.
[[#late-interpretation-or-e|Statement expansion]] allowed.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abz8?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abz9?>Functions.
[[#function-interpretation|Function calls]],
[[#partial-or-late-function|Partial function call
interpretation]].</para>
<remark><?xxe-sn 26stp2g6sxs 5?>interpreta - это так и нужно, или
неполное слово? - <emphasis role="bold"><?xxe-sn 26stp2g6sxs 6?>этот
кусок текста на сайте превратится в ссылку, это адрес ссылки, такой
должен быть</emphasis></remark>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abza?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzb?>Index operator e.g.
<code><?xxe-sn 26cy4nalqsw pu35zrt1abzc?>x = {1, 2, 3}.
y = x[0]</code>, <code><?xxe-sn 26t7ih8bitc 1?>info = {planet="Earth"}.
x = info["planet"]</code>.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abze?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzf?>List operators e.g.
<code><?xxe-sn 26t7ih8bitc 2?>x = [1..10]. y={"day",
"night"}</code>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1abzh?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1abzi?>Function Interpretation</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzj?>The whole function body may be
subject to interpretation if it consists of interpretable expressions
only.</para>
<programlisting xml:id="FnIntr_1"><?xxe-sn 26cy4nalqsw pu35zrt1abzk?>name="tests/interpretation.cpp: Interpretation.Doc_FnIntr_1"
unwrap = function(data::unknType, keys::unknType):: unknType; i12n(on)
{
loop fold(keys-&gt;key::string, data-&gt;record):: unknType
{
record[key]
}
}
test = function:: bool; entry
{
book = unwrap({
Library = {
Shelf = {
Book = "Aristotle's Politics"
}}}, {"Library", "Shelf", "Book"}):: unknType.
book == "Aristotle's Politics"
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzl?>The above example demonstrates
the <code><?xxe-sn 26cy4nalqsw pu35zrt1abzm?>unwrap</code> function which
is intended to be fully interpretable, as indicated by the function
header's annotation. Obviously, the interpretable function requires that
all its arguments are also interpretable. In this case the compiler is
able to calculate the function's result at compile time with no byte code
produced. Here is what the compiled code looks like (which will be also
optimized out during the consequent compilation phases):</para>
<programlisting xml:id="Alt_FnIntr_1"><?xxe-sn 26cy4nalqsw pu35zrt1abzn?>name="tests/interpretation.cpp: Interpretation.Doc_FnIntr_1"
test = function:: bool; entry
{
book = "Aristotle's Politics":: string; i12n(on).
book == "Aristotle's Politics"
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzo?>The example also reveals a number
of similarities with dynamically typed programming languages:</para>
<remark><?xxe-sn 26stp2g6sxs 7?>number of similarities - тут точно нужен
артикль, неопределенный (a) если в смысле "много схожестей", и
определенный (the) - если речь идет о точном их количестве. a dynamically
typed - неопределенный артикль никогда не употребляется при множественных
объектах - <emphasis role="bold"><?xxe-sn 26stp2g6sxs 8?>OK</emphasis></remark>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1abzp?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abzq?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzr?><emphasis><?xxe-sn 26cy4nalqsw pu35zrt1abzs?>Relaxed
types</emphasis>. Notice <code><?xxe-sn 26cy4nalqsw pu35zrt1abzt?>unknType</code>
type which has not been defined. It's interpreted well because the
compiler completely ignores the type system since everything can be
checked at compile time anyway. The Interpretation mode is exactly the
level where the relaxed type system is possible without any
performance penalties or safety concerns.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1abzu?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzv?><emphasis><?xxe-sn 26cy4nalqsw pu35zrt1abzw?>Introspection
abilities</emphasis>. Notice how it is allowed to treat list fields as
string keys, so functions like <code><?xxe-sn 26cy4nalqsw pu35zrt1abzx?>unwrap</code>
can get list field name as a parameter. Possible errors, such as the
list not having the requested field are easily spotted by the compiler
during interpretation and there are no concealed runtime bugs. In a
sense, it is a fair trade off between introspection expressiveness and
possible compilation errors.</para>
<remark><?xxe-sn 26stp2g6sxs 9?>no hard to catch runtime bugs - не
вполне ясно. В смысле, "легко заметить баги проявившиеся во время
операции"? Тогда лучше "its is easy to see runtime bugs", или может
"the runtime bugs are possible" (если смысл такой, что могут
проявиться ошибки/баги"). It's и другие подобные сокращения: лучше
употреблять полную форму - it is, так как it's это разговорный вариант
- <emphasis role="bold"><?xxe-sn 26stp2g6sxs a?>OK</emphasis>.</remark>
</listitem>
</itemizedlist>
<note>
<?xxe-sn 26cy4nalqsw pu35zrt1abzy?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1abzz?>Additional reason for the
arbitrary undefined type <code><?xxe-sn 26cy4nalqsw pu35zrt1ac00?>unknType</code>
being used in the example is to ensure that no compilation occurs and
everything is done at the interpretation mode.</para>
</note>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac01?>In simple cases interpretation
analysis could determine that a function is subject to interpretation with
no annotation hints provided.</para>
<programlisting xml:id="FnIntr_2"><?xxe-sn 26tbgov1xq8 1?>name="tests/interpretation.cpp: Interpretation.Doc_FnIntr_2"
unwrap = function(data::unknType, keys::unknType):: unknType
{
loop fold(keys-&gt;key::string, data-&gt;record):: unknType
{
record[key]
}
}
test = function:: bool; entry
{
book = unwrap({
Library = {
Shelf = {
Book = "Aristotle's Politics"
}}}, {"Library", "Shelf", "Book"}):: unknType; i12n(on).
book == "Aristotle's Politics"
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac03?>The only difference from the
example above is the lack of annotation hint for <code><?xxe-sn 26cy4nalqsw pu35zrt1ac04?>unwrap</code>.
It can be seen that interpretation of the variable <code><?xxe-sn 26cy4nalqsw pu35zrt1ac05?>book</code>
is required which in its turn depends on <code><?xxe-sn 26cy4nalqsw pu35zrt1ac06?>unwrap</code>.
In this case analysis is capable enough to determine that <code><?xxe-sn 26cy4nalqsw pu35zrt1ac07?>unwrap</code>
is indeed possible to interpret, so no errors occur.</para>
<remark><?xxe-sn 26stp2g6sxs b?>"Developer requires interpretation" - тут
речь о разработчике-программисте? Не вполне понятен смысл, поэтому пока
оставляю как есть. - <emphasis role="bold"><?xxe-sn 26stp2g6sxs c?>да
программист, исправил</emphasis></remark>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac08?>There are, however, more
complicated cases for interpretation analysis:</para>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1ac09?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac0a?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0b?>Direct recursion.
Interpretation analysis is able to correctly determine whether a
function involving direct recursion (where the function calls itself)
is subject to interpretation or not.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac0c?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0d?>Indirect recursion.
Currently, when processing the indirect recursion (where a function is
called not by itself but rather by another function), the analysis
usually fails and relies on manually provided annotation hints.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0e?>Below is an example of a direct
recursion:</para>
<programlisting xml:id="FnIntr_3"><?xxe-sn 26cy4nalqsw pu35zrt1ac0f?>name="tests/interpretation.cpp: Interpretation.Doc_FnIntr_3"
unwrap = function(data:: X):: bool
{
if (data[0] == "the-end"):: bool
{true} else {unwrap(data[0])}
}
entry = function:: bool; entry
{
unwrap({{{{"the-end"}}}}):: bool; i12n(on)
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0g?>Function <code><?xxe-sn 26cy4nalqsw pu35zrt1ac0h?>unwrap</code>
unwraps the nested list until the desired value is found. No function
level annotation is required.</para>
</section>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1ac0i?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1ac0j?>Late Interpretation or
Expansion</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0k?><emphasis><?xxe-sn 26stp2g6sxs d?>Late
Interpretation</emphasis> can be conceptualized as a <emphasis><?xxe-sn 26stp2g6sxs e?>partial</emphasis>
expansion, i.e. a simplification or elimination of interpretable parts of
certain statements.</para>
<programlisting xml:id="LateIntr_1"><?xxe-sn 26cy4nalqsw pu35zrt1ac0l?>name="tests/interpretation.cpp: Interpretation.Doc_LateIntr_1"
test = function(x:: int):: int; entry
{
comm= "inc":: string; i12n(on).
y= if (comm == "inc"):: int
{x + 1} else {x}.
y
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0m?>In this example, computation of
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac0n?>y</code> depends on
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac0o?>comm</code> and <code><?xxe-sn 26cy4nalqsw pu35zrt1ac0p?>x</code>.
On the one hand, <code><?xxe-sn 26cy4nalqsw pu35zrt1ac0q?>comm</code> has
an annotation that requires interpretation, while on the other hand
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac0r?>x</code> is unknown at the
compile-time and thus cannot be interpreted. In this case the only way to
satisfy contradictory requirements is to <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac0s?>expand</emphasis>
the <code><?xxe-sn 26cy4nalqsw pu35zrt1ac0t?>if</code> statement, since it
is only possible to interpret condition part of the statement, leaving
conditional blocks unchanged. In other words, the <code><?xxe-sn 26cy4nalqsw pu35zrt1ac0u?>if</code>
statement is <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac0v?>expanded</emphasis>
which results in only one of the child blocks being compiled,
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac0w?>x+1</code> in this example, based
on already known fact that the <code><?xxe-sn 26stp2g6sxs f?>else</code>
block would never be executed.</para>
<remark><?xxe-sn 26stp2g6sxs g?>"to interpret condition part of the
statement" - это не смог понять. - <emphasis role="bold"><?xxe-sn 26stp2g6sxs h?>`if
(...) {..} else {...}` is a statement. It consists of condition part `if
(..)`, and two blocks - "if-true" block and "if-false" block
</emphasis></remark>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0x?>Due to the fact that expansion,
as opposed to "pure interpretation", leaves some portion of the code for
subsequent compilation it can also be called <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac0y?>late
interpretation</emphasis> for the result depends on runtime information
and has memory and performance footprint.</para>
<remark><?xxe-sn 26stp2g6sxs i?>as having runtime footprint - не понял.
Что-то связанное с требованиями к памяти? Но это кажется о программах, а
не о interpretation - <emphasis role="bold"><?xxe-sn 26stp2g6sxs j?>переписал
фразу</emphasis></remark>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac0z?>Below is a more complex example
of a loop expansion:</para>
<programlisting xml:id="LateIntr_2"><?xxe-sn 26cy4nalqsw pu35zrt1ac10?>name="tests/interpretation.cpp: Interpretation.Doc_LateIntr_2"
main = function(x:: int):: int; entry
{
commands = {"inc", "double", "dec"}:: [string]; i12n(on).
loop fold(commands-&gt;comm::string, x-&gt;operand):: int
{
switch(comm):: int
case ("inc") {operand + 1}
case ("dec") {operand - 1}
case ("double") {operand * 2}
}
}
</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac11?>Identifier <code><?xxe-sn 26cy4nalqsw pu35zrt1ac12?>commands</code>
contains a list of operations that need to be interpreted as indicated by
the corresponding annotation. Operand <code><?xxe-sn 26cy4nalqsw pu35zrt1ac13?>x</code>
is assigned at runtime. This is the same situation as in previous example,
and it triggers expansion as expected. The result after expansion looks as
follows:</para>
<programlisting xml:id="Alt_LateIntr_2"><?xxe-sn 26cy4nalqsw pu35zrt1ac14?>name="tests/interpretation.cpp: Interpretation.Doc_LateIntr_2"
main = function(x:: int):: int; entry
{
x{1} = x + 1:: int.
x{2} = x{1} * 2:: int.
x{3} = x{2} * 1:: int.
x{3}
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac15?>In other words, this mimics the
well known loop unrolling technique by putting several copies of the loop
body in a row, each one for every item in the list <code><?xxe-sn 26stp2g6sxs k?>commands</code>.</para>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac16?>As of now, the following
statements support late interpretation:</para>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1ac17?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac18?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac19?>Branching statements:
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1a?>if</code>, <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1b?>switch</code>,
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1c?>switch variant</code>,
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1d?>switch late</code>.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac1e?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1f?>Loop statements:
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1g?>loop fold</code>.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac1h?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1i?>Functions.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac1j?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1k?>Other operators:
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1l?>query late</code>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1ac1m?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1ac1n?>Partial or Late Function
Interpretation</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1o?>Xreate supports cases where a
function has mixed arguments in terms of interpretation, some of which
need to be interpreted, while others need to be compiled.</para>
<programlisting xml:id="LateFnIntr_1"><?xxe-sn 26cy4nalqsw pu35zrt1ac1p?>name="tests/interpretation.cpp: Interpretation.Doc_LateFnIntr_1"
evaluate= function(argument:: num, code:: string; i12n(on)):: num
{
switch(code):: num
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
case default {argument}
}
main = function(init::int):: int; entry
{
commands= {"inc", "double", "dec"}:: [string]; i12n(on).
loop fold(commands-&gt;comm::string, init-&gt;operand):: int
{
evaluate(operand, comm)
}
}</programlisting>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1q?>Looking at the function
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1r?>evaluate</code>'s signature in
this example we can see only one argument <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1s?>code</code>
that requires interpretation. This means that the function <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1t?>evaluate</code>
is subject to a partial interpretation or, in other words,
<emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac1u?>late function
interpretation</emphasis>.</para>
<para><?xxe-sn 26stp2g6sxs n?>In general, to enable late interpretation
for a function, at least one of its arguments should be annotated as
<code><?xxe-sn 26cy4nalqsw pu35zrt1ac1v?>i12n(on)</code>. What compiler
does next is to generate a number of distinctive <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac1w?>function
specializations</emphasis>. Each unique combination of interpretable
argument values corresponds to its own function specialization. This
should be used with cautiousness, since compiler can generate large
amounts of code in some cases.</para>
<remark><?xxe-sn 26stp2g6sxs l?>What compiler does next is to generate
number - то же самое, что в примеч. ниже (a number - несколько, the number
- конкретное число).To enable late interpretation for function - тут перед
function обязательно нужен артикль - определенный (the), если речь идет о
evaluate, или неопределенный (а) если речь идет о любой функции (я указал
the) - <emphasis role="bold"><?xxe-sn 26stp2g6sxs m?>OK</emphasis></remark>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac1x?>Based on the above example, three
different <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1y?>evaluate</code>
specializations are generated as follows:</para>
<programlisting xml:id="Alt_LateFnIntr_1"><?xxe-sn 26cy4nalqsw pu35zrt1ac1z?>name="tests/interpretation.cpp: Interpretation.Doc_LateFnIntr_1"
main= function(init::int):: int; entry
{
operand = init:: int.
operand{1} = evaluate1(operand):: int.
operand{2} = evaluate2(operand{1})::int.
operand{3} = evaluate3(operand{2})::int.
operand(3)
}</programlisting>
</section>
<section>
<?xxe-sn 2f6e093xhxc 1?>
<title><?xxe-sn 2f6e093xhxc 2?>Queries</title>
<synopsis><?xxe-sn 2f6e093xhxc 3?>SYNTAX:
**intrinsic query** (//predicate//):: type; [//annotations-list//]</synopsis>
<itemizedlist>
<?xxe-sn 2f6e093xhxc 4?>
<listitem>
<?xxe-sn 2f6e093xhxc 5?>
<para><?xxe-sn 2f6e093xhxc 6?><emphasis><?xxe-sn 2f6e093xhxc 7?>predicate</emphasis>
Denotes a Transcend predicate.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2f6e093xhxc a?>Represents the value of the Transcend
predicate <emphasis><?xxe-sn 2f6e093xhxc b?>predicate</emphasis> in the
format as follows:</para>
<itemizedlist>
<?xxe-sn 2f6e093xhxc g?>
<listitem>
<?xxe-sn 2f6e093xhxc h?>
<para><?xxe-sn 2f6e093xhxc i?>If a predicate has only one argument,
returns a list of elements of an appropriate type: <code><?xxe-sn 2f6e093xhxc j?>int</code>,
<code><?xxe-sn 2f6e093xhxc k?>string</code>, variant or tuple.</para>
</listitem>
<listitem>
<?xxe-sn 2f6e093xhxc l?>
<para><?xxe-sn 2f6e093xhxc m?>in case of several arguments, the
arguments comprise a record. The function returns a list of
records.</para>
</listitem>
<listitem>
<?xxe-sn 2f6e093xhxc n?>
<para><?xxe-sn 2f6e093xhxc o?>Predicates correspond to
variants.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2f6e093xhxc 8?>Interpretation can be viewed as the middle
ground between high level Transcend and low level Brute. In essence, the
principal role of Interpretation is to serve as a link between them by
<emphasis><?xxe-sn 2f6e093xhxc 9?>interpreting</emphasis> data for Brute
from Transcend. The special built-in function <code><?xxe-sn 2f6e093xhxc c?>intrinsic query</code>
is provided to query data from Transcend allowing to process it
further.</para>
<para><?xxe-sn 2f6e093xhxc d?>As a short example, assume that we have
Transcend facts as follows:</para>
<programlisting><?xxe-sn 2f6e093xhxc e?>person("Ben").</programlisting>
<para><?xxe-sn 2f6e093xhxc f?>This data can be queried as below:</para>
<programlisting><?xxe-sn 2f6e093xhxc p?>Persons = type [string]. //we expect a list of strings
persons = function:: Persons
{
intrinsic query("person"):: Persons
}</programlisting>
<para><?xxe-sn 2f6e093xhxc q?>The <code><?xxe-sn 2f6e093xhxc r?>persons</code>
function in this example returns a list of persons supplied by Transcend.
The example can be slightly rewritten using <link
xlink:href="/d/syntax/#slave-types"><?xxe-sn 2f6e093xhxc s?>slave
types</link> which are reserved to automatically identify an appropriate
type for the returned value. The next excerpt is equivalent to the
previous one:</para>
<programlisting><?xxe-sn 2f6e093xhxc t?>Person = type slave person. //equivalent to string
Persons = type [Person]
persons = function:: Persons
{
intrinsic query("person"):: Persons
}</programlisting>
</section>
<section>
<?xxe-sn 2fxwo1r89a8 2?>
<title><?xxe-sn 2fxwo1r89a8 3?>Querying Example: GUI</title>
<para><?xxe-sn 2fxwo1r89a8 5?>Querying allows to use powerful Transcend
capabilities to solve convoluted problems, consequently retrieving
reasoning solutions by Brute for efficient processing. Consider a more
complicated example dealing with a GUI.</para>
<para><?xxe-sn 2fxwo1r89a8 6?>First, let us start off defining more or
less semantically an application's GUI on the Transcend level:</para>
<programlisting xml:id="IntrinsicQuery_2_GUI"><?xxe-sn 2fxwo1r89a8 7?>name="tests/association.cpp: Association.Doc_IntrinsicQuery_2", lines=15
%Layout consists of two blocks:
block(my_content; my_nav).
%Assign roles to the blocks:
role(my_content, body).
role(my_nav, navigation).
%Navigation block can be in either an iconized or expanded form:
form(none; expanded; iconized).
allowed_form(my_nav, (expanded; iconized)).
%Visual theme:
background(my_content, color(blue)).
background(my_nav, color(grey)).</programlisting>
<para><?xxe-sn 2fxwo1r89a8 8?>Above we have described GUI consisting of
two blocks: main content and navigation blocks. The same application can
look differently depending on a platform's or viewport properties. Let us
define a platform:</para>
<programlisting xml:id="IntrinsicQuery_2_Platform"><?xxe-sn 2fxwo1r89a8 9?>name="tests/association.cpp: Association.Doc_IntrinsicQuery_2", lines=15
% The height is greater than the viewport's width:
orientation(portrait).</programlisting>
<para><?xxe-sn 2fxwo1r89a8 a?>Having an application's semantic description
as well as a platform's description we can now combine them using
additional rules to produce the final result: how the application should
look like on the given platform.</para>
<programlisting xml:id="IntrinsicQuery_2_Rules"><?xxe-sn 2fxwo1r89a8 b?>name="tests/association.cpp: Association.Doc_IntrinsicQuery_2", lines=15
% Portrait orientation rules:
%Determine appopriate navigation list's form:
form(Nav, iconized):-
orientation(portrait);
allowed_form(Nav, iconized);
role(Nav, navigation).
%Determine blocks' layout:
align(Nav, bottom_of(Body)):-
orientation(portrait);
role(Nav, navigation);
role(Body, body).
% Landscape orientation rules:
form(Nav, expanded):-
orientation(landscape);
allowed_form(Nav, expanded);
role(Nav, navigation).
align(Nav, left_of(Body)):-
orientation(landscape);
role(Nav, navigation);
role(Body, body).</programlisting>
<para><?xxe-sn 2fxwo1r89a8 c?>In short, the rules above read that we place
the expanded navigation block <code><?xxe-sn 2fxwo1r89a8 d?>my_nav</code>
and the content block <code><?xxe-sn 2fxwo1r89a8 e?>my_content</code> in a
row for wide displays; conversely, <code><?xxe-sn 2fxwo1r89a8 f?>my_content</code>
and iconized <code><?xxe-sn 2fxwo1r89a8 g?>my_nav</code> on top of each
other for narrow displays.</para>
<para><?xxe-sn 2fxwo1r89a8 h?>After Transcend has decided actual forms and
blocks alignment, the next step is to retrieve solutions denoted by the
<code><?xxe-sn 2fxwo1r89a8 i?>align</code> and <code><?xxe-sn 2fxwo1r89a8 j?>form</code>
predicates and to actually draw GUI elements:</para>
<programlisting xml:id="IntrinsicQuery_2_Code"><?xxe-sn 2fxwo1r89a8 k?>name="tests/association.cpp: Association.Doc_IntrinsicQuery_2", lines=15
//Define types:
Block = type slave block.
Role = type variant {body, navigation}.
Alignment = type variant{
- bottom_of:: Block,
- left_of::Block
+ bottom_of(ref :: Block),
+ left_of(ref :: Block)
}.
Layout = type {Role, Alignment}.
//Determine role and form:
drawBlock = function(block:: Block):: Drawing
{
forms = intrinsic query ("form"):: [Form].
formCurrent = getBlockForm(forms, block):: Form.
roles = intrinsic query ("role"):: [Role].
roleCurrent = getBlockRole(block):: Role.
switch variant (roleCurrent):: Drawing
case (body)
{drawBody(formCurrent)}
case (navigation)
{drawNavigation(formCurrent)}
}
//Determine layout
draw = function:: Drawing; entry
{
layout = intrinsic query ("layout"):: Layout.
blockA = layout[0]:: Block.
switch variant (layout[1]-&gt;blockB):: Drawing
case (bottom_of)
- {drawVerical(blockA, blockB)}
+ {drawVerical(blockA, blockB["ref"])}
case (left_of)
- {drawHorizontal(blockA, blockB)}
+ {drawHorizontal(blockA, blockB["ref"])}
}</programlisting>
<para><?xxe-sn 2fxwo1r89a8 l?>Notice that the <code><?xxe-sn 2fxwo1r89a8 m?>draw</code>
and <code><?xxe-sn 2fxwo1r89a8 n?>drawBlock</code> functions work with
compile time data from Transcend, thus all this code after interpretation
gets simplified into the following:</para>
<programlisting><?xxe-sn 2fxwo1r89a8 o?>drawVertical(drawBody(none()), drawNavigation(iconized())).</programlisting>
<para><?xxe-sn 2fxwo1r89a8 p?>The example above demonstrates the
possibility to delegate to Transcend <emphasis><?xxe-sn 2fxwo1r89a8 q?>intelligent
tasks</emphasis>, such as adapting a GUI to a particular platform, and
leaving Brute with efficient implementation matters.</para>
</section>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1ac20?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1ac21?>Domain Specific Languages and
Interpretation</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac22?>DSL is an idea of expressing
various concepts in a lapidary and concise form. Xreate recognizes and
acknowledges very successful and beneficial DSL usage in certain areas,
primarily to express <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac23?>queries</emphasis>
and <emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac24?>configs</emphasis>, to
name a few. It is possible to use interpretation abilities to emulate DSL.
Developer can express the desired functionality in the form of nested
lists of numbers, variants and strings which are then processed by a
partially interpreted function. Such function in its turn transforms the
input data into a set of low level compilation instructions so there is no
runtime overhead.</para>
</section>
<section>
<?xxe-sn 26cy4nalqsw pu35zrt1ac25?>
<title><?xxe-sn 26cy4nalqsw pu35zrt1ac26?>On Interpretation
Analysis</title>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac27?>Analysis follows classical
<emphasis><?xxe-sn 26stp2g6sxs o?>type reconstruction</emphasis>
algorithms to determine which expressions are subject to interpretation
and check the correctness of reconstruction w.r.t. developer-provided
annotations. Analysis consists of two general parts:</para>
<itemizedlist>
<?xxe-sn 26cy4nalqsw pu35zrt1ac28?>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac29?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac2a?><emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac2b?>Inference</emphasis>.
Infers if it is possible to interpret an expression based on its
already inferred argument's decisions.</para>
</listitem>
<listitem>
<?xxe-sn 26cy4nalqsw pu35zrt1ac2c?>
<para><?xxe-sn 26cy4nalqsw pu35zrt1ac2d?><emphasis><?xxe-sn 26cy4nalqsw pu35zrt1ac2e?>Unification</emphasis>.
Assigns an appropriate decision w.r.t. previously inferred
expectations and developer-provided hints as well.</para>
</listitem>
</itemizedlist>
</section>
</chapter>
<?xxe-revisions
#10 2019-05-28T10:00:12Z pgess
#9 2019-05-16T14:57:00Z pgess
1sPEAAABgoFMAIIugoB4ABmBK2J1dnd5ejIzNDU3ODd5dzBzNnZiNDIzNDU2c4G0YxMOExhDlTZj
GwEBM4F3UwoBAUNVY1JzCgEBM4NdcwoTBDMFU4ELUwhTeXMKAQEzgThzCgEBU4IecwsTD0M+M4RG
cwsTBzNZcwsBAWM5cwsBAUNPcwsBAWM0cwsBAUNUcwsTBBMFY4EBcwsBAWMmcwsBAUN/cwsTBDNI
Y4d9AQkTBDMHQxojCwEBUyVjCgEBM4E5cwoBAVNhcwoBARMFM1tzCgEBY5ENAIYmg3iBrk6MZ4lW
gbA+ggJZNl02ohSVaINwhS+BFzaBBDaBQzaBhn6aQYJ1NtV4hFc2ZDZENlo2PzaBkkqBjU1nNoEM
NjE2zWiaNoFVi1W5fbclL+99ATCygUSymXNxsmY=
#8 2019-05-15T14:56:03Z pgess
1sPEAAABgoB4AC2CgHcAABQSc4HLSiMEE4tOEwcTB1MHMyFDqSUAgdY4gctKga9vhRKHQexAhEg=
#7 2019-05-14T17:52:28Z pgess
1sPEAAABgoB7AINMgfUKABqBcYE4LiBBaXc/PmZ5Pz4lIEhsb25nZW50ZXh0OSBzgbxmE4NIEwQT
CkMEYwUBA1MJUwlDG1OCYRMKYxFjgi8zgVtTBxMGQ4JQEwRjBlMMQwYBAWMMQwQzBTMIQwYzBWNE
QwUTCWMGcwpjBzMFQwVDBFMEY4EmIxYBA0M8Y0VjdUMZUxZTCDMMYzpTgQEBAWNTgxYBBjMJ3QEC
Y4EyM4EPgxZDBGMGAQEzhGwTB0NmExFjggpDBEMQqTMLMwxzEVMMQ1FDBTMHUwQTCIMKgxFTFeFj
CFMPYxEzF0MFQxxjSnMFMxxTRmMcIwkTCDNqkwUTFiMOcwcBAWMRcwUzF1NBYxsjCXMIEwgzbRMU
M496AIG8aNt9hiaPBQ7kTzqBnh4smj2CDGuCOsJWljiBaYR/kBuBk2ueRpJ4qQX2NpgUiUHRKrFs
ozS4C6AUJoEBcoHZB5QfhRWBsAKJT4Imgik6eDoMIoECP4ECaoFfDguBN2qBRU0HgaRIhHKTb32Q
PoJNh3iBw2GBlDLvmAuWCV2sN41igbovPZKBmW+pEKBqgU8QEJBUGx0/Th1PAYHlbCQ/gcRYAeyD
ST8VGEoB7IGfayuBiiiGKg==
#6 2018-12-15T16:59:22Z pgess
1sPEAAABgfUPABeBxBEAAAkHc4G0NSMWI49GAIG8f4HEEQ==
#5 2018-12-15T16:52:17Z pgess
1sPEAAABgcQRADKBw2wAABoRc6Y2IwkTgR+DCYNeM0RDBBMLQx4TCDOBmi4A3R2mTqpOghXYbqY6
UpIdLg==
#4 2018-12-15T16:19:00Z pgess
1sPEAAABgcNsAEyBw2AAACYfc8wdExoTkBhDCmMEEwRTG1M3EwljhFITF0MlQ+BbUxVDEFMLMwsA
zUnMM5IgrEa+b5AnJJckN4sitEqFIJF9gXKROuEM
#3 2018-12-15T14:05:19Z pgess
1sPEAAABgcNhAIVpgb9cADODNIF5ZD8+PSB7MSwgMiwgPSA9ID0ga2MwMj8+NC0gMXB6MT0gICsg
MTIqIDIzLTF9KDEpMygyc5EoEyEBA0MUIwtTBzMGMwpTC2MSMxdDElMFIzhjmhYBCUMFAQJTDmMj
AQIzEyMEQ4E1AQJjgnczIQEBQwgzMGMZM0dTCEMRYz0zEkMWUxZjGCMIMyJTNGMIEwVjIpM4U4Qm
gyAzBEMEYzKTEpMJUzMTBGOYfYMfAQUjBjM0Mw2TCGNLIw6TEWMHYwcjBZMEkzKTDpMOEwRjECMI
UxIjCjMSIwxzIiMJMy+DCGMKcwVjCUMcIwZDN2ONe4MfUwUjGDMMUwaTBjMuQ0lTDhMEY4Vdgx9D
BVMEgwxjF3MEUxpzEHMFMxpjCDMYcwUjOkOSGoMfMwVzBIMMcwxTI3MEU0kzPpMIUzBzCGMmQyZT
JGODYiMhAQFDHTMLcwQzDkMFUxEzBGMO7ZMGMzxDjFpDIQEBUwoTCkMxcwRDPWMGMyNDI1MjYw8z
RCMbQ0NjQpMIMx6TP1OONnMhAQFzCgEDUwmDDxMEMwRzBAEBUwrNEwgBASMxAQOTBJMIAQGDMdVz
DjMOgwtzBEMJkwljBzMFkwoBAkMUcwSTDDMTAQMjDwEBQwszCQECUwhDDGMFgxQTM1OPRgCDKY5u
xjQX2CsKFAkUFRDMNTyaJAoPKL8zGoE6h3kig3AuF9A2Sg87EBIQARgejyuSUkH5WamEXI45ozrM
3IdgkwxBqaJGoGOBA1QZVYKCHV8R4pzM5ygWARABEgEWgV8j36YoUqUcpCilV0GkSamOLJJiWoE4
WQQqR5I2EamGEI4581Q2GmlSLxwEjpcqVKmSTRfzQ142JkdUBKg2IiIihwAiy1U2/EQeA1YgjLv2
a2GSMSKSG41nNjQ/BCEhIRKXO1xBVEb0Wk1vlwEDkmQtNopXojCEaUGUaSgyF4GNdck2kmIf/QBW
bjGMbg0nEDUWAiCxgZoESw==
#2 2018-12-15T11:27:17Z pgess
1sPEAAABgb9cAIE1gb9cAARlRXpkLmdznFkTgVyTFUODOJM/Y4FCkz5DgVOTPmMuQwVjNpM+Q4Eh
EyZDgxVjBGNrExQBAkMrAQFTCJM+Yy4TBEM3AQFTICMecxBD1zkzJkOKFVM/U3mDbBMIQz5DfJMV
cxAzi14TBGOddwCcWlqBclqDeFqCAVqCEoxBgR1agSiIL4FItBSDGYM1dpAgWnKRIIYrX4FRTE7C
IZVJi0+KVa6RUs4vgTNaTIEihhaLYg==
#1 2018-12-07T16:28:26Z Acer2
1sPEAAABgb9gAIckgbYGAEGDeoJgeWNzIHdhcnJpYzJmZ29jMjJpMmtob25vJ3MybWMybj8+SW9w
MnI/PjJ0SUZjMnZjMnhnZW9mIGBgMzMxYzJ6Pz5zhE0TDSMHQyoBAkMLUw0TEGMHEwgBATMIIwdD
BiMEYwlDBUMRYwRTBmMNMwZTBUMEMwYjBbXbE4JtQyQBAyMpAQFTgxUjCWMJEwZDQEOETgEBU2Bj
J4MkAQIzBEMlAQIzPJMJkywzj3gjJlMpAQKTT5MJkwgTNVOLUTMEUxkzgT9jB1MJYwSDB0MHAQJD
BAECMwVTCBMIAQJDBVM0MwQzg0ZzJhMEgyUBAlOCC5MaExMBBVOBI5MJkwhDhCAzCBMHExGTNUOC
MgEBYwaTBEMHQwZTCEMNYwRjBRMEQwUTCJMFMwdjBFMekwkjJgEBUykBATOCe5MJkwiDJhMEUyUB
BDOBPiMKkwiTDEMQg4IaMwdjBFMNUwUTBZMJk0ETDkMJU4Z6YwljD0NHM2RDCUMLEw8TJTMXUzMj
JkMEgyUBAmOBVJMJky5jMoMOIwlTgTSTCYOBEmM+Y4E/kwlDPhMVcxBjhUhTCWMJgzxjBXMJQwZT
CEMIY4dcAQITEmOBLiMUIwQzK0OBG0MmEwYzBVMiIyZjKAEDQ1WTCZMuM4FnYxuDMBMoAQNjgUqT
CZMuY4USU3kBAjMFY4QerPlTC0OTOkMiYwRDg2eTJdMjJQECM4E2kwmTCJMmEygBBZOCOZMJky1D
jVEzE0ODV4MGUwkTCIMEEw2DPlOCHACJB6x4vjugO4xKhQ+nIIRpCJAODpEOCMRQEZIJqwoRhEGP
QJRehmW9d9Bwnm2FS5ZljgSGDKs7gj6FGYVKSIRUYaCZG7xbRbbegUmROsEJwrbenGOCZo1ii1cb
myGNMacvzp5AVpN80nSRUwyoIY9CPJ+aMfuDZLaDNYINtt6BboQsukKXNGNZhHuh3AGCValMEMQ0
khq5Ra1AhEsSl1yrTq4ntoxnJ4Evtt4wnUO6HbE3hXjeY4FooNcerGiZGJAWhhO23oN4ljZYtFWQ
docWU9wJhwnUPZMriRgejyuLWftRtt6CXviEL0koqLALgVEogUycWktkhV+pZ/g3iMcDsnSlAIFs
pVaHcIFCk2jQC4FxgRyFVIFhV5pmwUFAtt6CToJnjaEkgmW23oJWhRWdZX6GVIYP6GKEWJlNrkiU
ER+IUpdyhAW23h+iQsm23oMpjXQfYYN3xkzBuF+zjAM=
-?>
\ No newline at end of file
+?>
diff --git a/documentation/Syntax/syntax.xml b/documentation/Syntax/syntax.xml
index 9d47543..560e26b 100644
--- a/documentation/Syntax/syntax.xml
+++ b/documentation/Syntax/syntax.xml
@@ -1,1290 +1,1290 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 26yv439af40 59?>
<title><?xxe-sn 26yv439af40 5a?>Syntax</title>
<para><?xxe-sn 26yv439af40 5v?>There is a number of principles the Xreate
syntax is based on:</para>
<itemizedlist>
<?xxe-sn 26yv439af40 5w?>
<listitem>
<?xxe-sn 26yv439af40 5x?>
<para><?xxe-sn 26yv439af40 5y?>Follows SSA(single assignment) form: each
identifier is defined only once and no redefinitions allowed.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 5z?>
<para><?xxe-sn 26yv439af40 60?>Follows literate programming principles
where possible. For example, identifiers can be defined in any order
reflecting personal preferences and convenience for a developer.
Regardless of the definition order, expressions are computed based on
dependencies between them. Literate programming principles from a
practical point of view simplify code testing, support, catching
regressions, etc.</para>
</listitem>
</itemizedlist>
<section>
<?xxe-sn 26yv439af40 61?>
<title><?xxe-sn 26yv439af40 62?>Literals and Expressions</title>
<para><?xxe-sn 26yv439af40 63?>Xreate expressions have a form:</para>
<synopsis><?xxe-sn 26yv439af40 64?>SYNTAX:
//expression// [:: //type//; //annotations-list// ]</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 fd?>
<listitem>
<?xxe-sn 26yv439af40 fe?>
<para><?xxe-sn 26yv439af40 ff?><emphasis><?xxe-sn 26yv439af40 fg?>annotation-list</emphasis>
is a list of annotations delimited by semicolon.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 67?>Expressions consist of literals and various
operations as follows:</para>
<informaltable>
<?xxe-sn 26yv439af40 68?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 69?>
<colspec colwidth="115*"><?xxe-sn 26yv439af40 6a?></colspec>
<colspec colwidth="885*"><?xxe-sn 26yv439af40 6b?></colspec>
<tbody>
<?xxe-sn 26yv439af40 6c?>
<row>
<?xxe-sn 26yv439af40 6d?>
<entry><?xxe-sn 26yv439af40 6e?>Literals</entry>
<entry><?xxe-sn 26yv439af40 6f?>numbers, strings: <code><?xxe-sn 2ese8ot7ke8 e?>5</code>,
<code><?xxe-sn 2ese8ot7ke8 f?>"Nimefurahi kukujua"</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 6h?>
<entry><?xxe-sn 26yv439af40 6i?>Lists, records</entry>
<entry><?xxe-sn 26yv439af40 6j?><emphasis><?xxe-sn 2ese8ot7ke8 c?>Record</emphasis>
is a collection of elements of different types - <code><?xxe-sn 26yv439af40 6k?>{year = 1934, month = "april"}</code>.
<emphasis><?xxe-sn 2ese8ot7ke8 d?>List</emphasis> is a collection
of elements of the same type without keys - <code><?xxe-sn 26yv439af40 6l?>{16, 8, 3}</code>.
Range is a specific form of a list - <code><?xxe-sn 2apiasqubk0 4?>[1..18]</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 6m?>
<entry><?xxe-sn 26yv439af40 6n?>Arithmetic operations</entry>
<entry><?xxe-sn 26yv439af40 6o?>Basic arithmetic operations:
<code><?xxe-sn 2ese8ot7ke8 g?>+</code>, <code><?xxe-sn 2ese8ot7ke8 h?>-</code>,
<code><?xxe-sn 2ese8ot7ke8 i?>*</code>, <code><?xxe-sn 2ese8ot7ke8 j?>/</code>.</entry>
</row>
<row>
<?xxe-sn 2evpzktyvg7 -wunr7fl0rw8j?>
<entry><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8i?>Boolean
operations</entry>
<entry><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8h?>Negation example:
<code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8g?>-isEmty()</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 6q?>
<entry><?xxe-sn 26yv439af40 6r?>Relations</entry>
<entry><?xxe-sn 26yv439af40 6s?><code><?xxe-sn 2ese8ot7ke8 r?>==</code>,
<code><?xxe-sn 2ese8ot7ke8 s?>!=</code>, <code><?xxe-sn 2ese8ot7ke8 t?>&lt;&gt;</code>,
<code><?xxe-sn 2ese8ot7ke8 u?>&lt;</code>, <code><?xxe-sn 2ese8ot7ke8 v?>&lt;=</code>,
<code><?xxe-sn 2ese8ot7ke8 w?>&gt;</code>, <code><?xxe-sn 2ese8ot7ke8 x?>&gt;=</code>.
Both <code><?xxe-sn 2ese8ot7ke8 y?>!=</code>, <code><?xxe-sn 2ese8ot7ke8 z?>&lt;&gt;</code>
mean <emphasis><?xxe-sn 26yv439af40 6v?>not equal</emphasis>
relation. Examples: <code><?xxe-sn 2ese8ot7ke8 10?>8&gt;=3</code>,
<code><?xxe-sn 2ese8ot7ke8 11?>"Blue" &lt;&gt; "Green"</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 6x?>
<entry><?xxe-sn 26yv439af40 6y?>List and record operations</entry>
<entry><?xxe-sn 26yv439af40 6z?>The <emphasis><?xxe-sn 26yv439af40 70?>index</emphasis>
operation to access individual elements of a list or record.
Example: <code><?xxe-sn 2ese8ot7ke8 12?>colors = {"Green", "Blue"}::[string]. color = colors[0]:: string.</code>
Accesing a record's element: <code><?xxe-sn 2ese8ot7ke8 13?>date = {year = 1934, month = "april"}. year = date["year"].</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 73?>
<entry><?xxe-sn 26yv439af40 74?>Identifiers</entry>
<entry><?xxe-sn 26yv439af40 75?>Example: <code><?xxe-sn 26yv439af40 76?>a - b</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 77?>
<entry><?xxe-sn 26yv439af40 78?>Functions</entry>
<entry><?xxe-sn 26yv439af40 79?>Example: <code><?xxe-sn 26yv439af40 7a?>result = isOdd(6):: bool.</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
<?xxe-sn 2evpzktyvg7 -wunr7fl0rw8v?>
<title><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8u?>Annotations</title>
<para><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8t?>This chapter is about Brute
syntax. See <link xlink:href="/d/transcend/"><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8l?>Transcend</link>
for details regarding Transcend and annotations syntax.</para>
</section>
<section>
<?xxe-sn 26yv439af40 7b?>
<title><?xxe-sn 26yv439af40 7c?>Code Blocks</title>
<para><?xxe-sn 26yv439af40 7d?>Code block is a list of expressions
delimited by a period. It has a <emphasis><?xxe-sn 26yv439af40 7e?>body</emphasis>
- the main expression along with optional identifiers' definitions.</para>
<synopsis><?xxe-sn 26yv439af40 7f?>SYNTAX:
{
[//ident// = //expression//. | //body-expression//. ]..
}</synopsis>
<para><?xxe-sn 26yv439af40 7g?>Code blocks consist of <emphasis><?xxe-sn 26yv439af40 7h?>a
body expression</emphasis> and an optional set of assignments to define
identifiers used in the body expression. A code block's computation result
is defined as a result of computing its body expression. Identifiers are
computed before expressions they are appear in, regardless of a
definitions' order.</para>
<programlisting xml:id="CodeBlocks1"><?xxe-sn 26yv439af40 7i?>name="tests/ast.cpp: AST.Doc_CodeBlocks1"
test = function:: int; entry
{
a + b:: int
a = 10:: int.
b = 2:: int.
}</programlisting>
<para><?xxe-sn 26yv439af40 7j?>Above is an example of the code block with
<code><?xxe-sn 26yv439af40 7k?>a+b</code> as its body expression(because
it does not have a form of an assignment). In this case the body depends
on the identifiers <code><?xxe-sn 26yv439af40 7l?>a</code>,
<code><?xxe-sn 26yv439af40 7m?>b</code> so the compiler computes both of
them beforehand.</para>
<para><?xxe-sn 26yv439af40 7n?>A computation order depends only on
dependencies between expressions. This approach has properties as
follows:</para>
<itemizedlist>
<?xxe-sn 26yv439af40 7o?>
<listitem>
<?xxe-sn 26yv439af40 7p?>
<para><?xxe-sn 26yv439af40 7q?>Mutually independent identifiers can be
evaluated in any order.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 7r?>
<para><?xxe-sn 26yv439af40 7s?>An identifier computed only if it is
required(at least transitively) by a code block's body
expression.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 26yv439af40 7t?>
<title><?xxe-sn 26yv439af40 7u?>Functions</title>
<synopsis><?xxe-sn 26yv439af40 7v?>SYNTAX:
//function-name// **=** **function** **(**[//argument//:: //type//[; //annotation-list//]]...**)::** //return-type// [; //annotations//]...
//function-block//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 7w?>
<listitem>
<?xxe-sn 26yv439af40 7x?>
<para><?xxe-sn 26yv439af40 7y?><emphasis><?xxe-sn 26yv439af40 7z?>function-name</emphasis>
Name of a function.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 80?>
<para><?xxe-sn 26yv439af40 81?><emphasis><?xxe-sn 26yv439af40 82?>argument</emphasis>
Formal parameters. Arguments are delimited by comma.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 83?>
<para><?xxe-sn 26yv439af40 84?><emphasis><?xxe-sn 26yv439af40 85?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 86?>return-type</emphasis> Formal
parameter's and returning value's types.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 87?>
<para><?xxe-sn 26yv439af40 88?><emphasis><?xxe-sn 26yv439af40 89?>function-block</emphasis>
Code block that acts as a function's definition.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 8a?>
<para><?xxe-sn 26yv439af40 8b?><emphasis><?xxe-sn 26yv439af40 8c?>annotations</emphasis>
List of annotations delimited by semicolon.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 8d?>Below is an example of the function
<code><?xxe-sn 26yv439af40 8e?>sum</code> returning sum of its two
arguments. Moreover there are several annotations defined. First
annotation <code><?xxe-sn 26yv439af40 8f?>entry</code> has a special
meaning — it depicts an entry point or a main function in a program.
Second annotation <code><?xxe-sn 26yv439af40 8g?>status(needs_review)</code>
is a demonstration that developers can annotate functions using custom
annotations to express related intentions or properties.</para>
<programlisting xml:id="Functions1"><?xxe-sn 26yv439af40 8h?>name="tests/ast.cpp: AST.Doc_Functions1"
sum = function(x:: int, y:: int):: int; entry; status(needs_review)
{
x + y
}</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 8i?>
<title><?xxe-sn 26yv439af40 8j?>Function Specializations</title>
<synopsis><?xxe-sn 26yv439af40 8k?>SYNTAX:
**guard::** //annotation//
{
//functions-list//
}</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 8l?>
<listitem>
<?xxe-sn 26yv439af40 8m?>
<para><?xxe-sn 26yv439af40 8n?><emphasis><?xxe-sn 26yv439af40 8o?>annotation</emphasis>
Guard expressed in the form of an annotation.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 8p?>
<para><?xxe-sn 26yv439af40 8q?><emphasis><?xxe-sn 26yv439af40 8r?>functions-list</emphasis>
One or more functions that share the same guard.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 8s?>Specializations is a crucial Xreate concept
serving as the principal connection between Transcend and Brute levels.
Xreate allows several functions to share the same name; in this case they
are called <emphasis><?xxe-sn 26yv439af40 fk?> specializations</emphasis>.
This is a syntactic foundation for <emphasis><?xxe-sn 26yv439af40 8u?>function
level <link xlink:href="/d/concepts/polymorphism/"><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8k?>polymorphism</link></emphasis>,
i.e. ability for the compiler to decide which exactly function is called
out of several available options. The polymorphism resolution can happen
during compilation(early polymorphism) or at run-time(late
polymorphism).</para>
<para><?xxe-sn 26yv439af40 8v?>Functions with the same name, i.e.
different specializations must have identifiers called <emphasis><?xxe-sn 26yv439af40 8w?>guards</emphasis>
to uniquely define a specialization. In this sense, a shared name is just
a placeholder, which only along with a guard comprise the fully qualified
exact function identifier. On the Brute level it is possible to specify
only a function's shared name for invocation. On the other hand, Transcend
is responsible to supply a guard part. When a function is actually called
by its name in a program it's expected that the resolution is already done
by Transcend at some time earlier and it supplies the correct guard to
uniquely specify which exactly specialization to call. This gives
Transcend a deep control over an actual program behaviour.</para>
<para><?xxe-sn 26yv439af40 8x?>An example:</para>
<programlisting xml:id="FunctionSpecialization1"><?xxe-sn 26yv439af40 8y?>name="tests/ast.cpp: AST.Doc_FunctionSpecializations1", lines=15
guard:: safe_enviroment
{
sum = function (a::int, b::int):: int
{
result = a + b:: int.
if (-isLastOpOverflow(result)):: int
{
result
}
else
{
overflowErrorCode()
}
}
}
guard:: fast_enviroment
{
sum = function (a::int, b::int) :: int
{
a + b
}
}</programlisting>
<para><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8f?>To alter existing code behaviour
it's always possible to add new specializations and adjust Transcend rules
to specify situations when a new specialization should(or should not) be
used.</para>
<note>
<?xxe-sn 26yv439af40 8z?>
<para><?xxe-sn 26yv439af40 90?>See <link
xlink:href="/d/transcend/ast-api/#function-s-specializatio"><?xxe-sn 26yv439af40 91?>API</link>
to get more detailed information on how guards are processed on the
Transcend side.</para>
</note>
</section>
<section>
<?xxe-sn 26yv439af40 92?>
<title><?xxe-sn 26yv439af40 93?>Branch Statements</title>
<section>
<?xxe-sn 26yv439af40 94?>
<title><?xxe-sn 26yv439af40 95?>IF Statement</title>
<synopsis><?xxe-sn 26yv439af40 96?>SYNTAX:
**if (** //condition// **)::** //type// [; //annotations// ]..
//block-true//
**else**
//block-false//</synopsis>
<para><?xxe-sn 26yv439af40 97?>The <code><?xxe-sn 26yv439af40 fh?>if</code>
statement executes <emphasis><?xxe-sn 26yv439af40 98?>block-true</emphasis>
or <emphasis><?xxe-sn 26yv439af40 99?>block-false</emphasis> depending
on the <emphasis><?xxe-sn 26yv439af40 9a?>condition</emphasis>
evaluation's result.</para>
<para><?xxe-sn 26yv439af40 9b?>Example:</para>
<programlisting xml:id="IfStatement1"><?xxe-sn 26yv439af40 9c?>name="tests/ast.cpp: AST.Doc_BranchStatements"
answer = if (question == "Favorite color?"):: string
{"Yellow"} else {"Don't know"}.</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 9d?>
<title><?xxe-sn 26yv439af40 9e?>SWITCH Statement</title>
<synopsis><?xxe-sn 26yv439af40 9f?>SYNTAX:
**switch (** //condition// **)** :: //type// [; //annotations//]..
[**case (** //guard// **)** code-block]..
**case default** //default-code-block//
</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 9g?>
<listitem>
<?xxe-sn 26yv439af40 9h?>
<para><?xxe-sn 26yv439af40 9i?><emphasis><?xxe-sn 26yv439af40 9j?>condition</emphasis>
Expression to to decide which branch to execute next.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 9k?>
<para><?xxe-sn 26yv439af40 9l?><emphasis><?xxe-sn 26yv439af40 9m?>guard</emphasis>
Value to match against <emphasis><?xxe-sn 26yv439af40 9n?>condition.</emphasis></para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 9o?>
<para><?xxe-sn 26yv439af40 9p?><emphasis><?xxe-sn 26yv439af40 9q?>default-code-block</emphasis>
Executed if no appropriate case found.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 9r?>The <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8e?>switch</code>
statement evaluation's result is that of the branch whose
<emphasis><?xxe-sn 26yv439af40 9s?>guard</emphasis> matches the
<emphasis><?xxe-sn 26yv439af40 9t?>condition</emphasis>.</para>
<para><?xxe-sn 26yv439af40 9u?>An example:</para>
<programlisting xml:id="SwitchStatement1"><?xxe-sn 26yv439af40 9v?>name="tests/ast.cpp: AST.Doc_BranchStatements"
monthName = switch(monthNum) :: string
case (1) {"Jan"}
case (2) {"Feb"}
case default {"It's strange..an unexpected month"}.</programlisting>
</section>
</section>
<section>
<?xxe-sn 26yv439af40 9w?>
<title><?xxe-sn 26yv439af40 9x?>Loops</title>
<para><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8d?>Xreate loops are constructed in
such a way that they hide actually mutable operations semantic under an
immutable facade compatible with a single assignment form.</para>
<section>
<?xxe-sn 26yv439af40 9y?>
<title><?xxe-sn 26yv439af40 9z?>LOOP Statement</title>
<synopsis><?xxe-sn 26yv439af40 a0?>SYNTAX:
**loop (** //init-value// **-&gt;** //accumulator// **)::** //type// [; //annotations//] //loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 a1?>
<listitem>
<?xxe-sn 26yv439af40 a2?>
<para><?xxe-sn 26yv439af40 a3?><emphasis><?xxe-sn 26yv439af40 a4?>init-value</emphasis>
Initial value a loop starts from.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 a5?>
<para><?xxe-sn 26yv439af40 a6?><emphasis><?xxe-sn 26yv439af40 a7?>accumulator</emphasis>
Identifier which holds loop's result after each iteration.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 a8?>For each iteration <emphasis><?xxe-sn 26yv439af40 a9?>accumulator</emphasis>
assumes the result of a previous iteration or <emphasis><?xxe-sn 26yv439af40 aa?>init-value</emphasis>
for the first iteration. The result of <emphasis><?xxe-sn 26yv439af40 ab?>loop-body</emphasis>
evaluation is used as a <emphasis><?xxe-sn 26yv439af40 ac?>accumulator</emphasis>'s
next iteration value and as an overall loop statement result after the
last iteration.</para>
<para><?xxe-sn 26yv439af40 ad?>Note, that this notation does not have an
explicit termination condition! The compiler relies on the loop body's
fixed point in order to decide when to interrupt the loop. Consider an
example:</para>
<programlisting xml:id="LoopStatement1"><?xxe-sn 26yv439af40 ae?>COUNTEREXAMPLE, name="tests/ast.cpp: AST.Doc_LoopStatements"
//an infinite loop
answer = loop (2 -&gt; x) :: int
{
if(IsPerfect(x)):: int {x} else {x+1}
}.</programlisting>
<para><?xxe-sn 26yv439af40 af?>The example tests numbers for being
perfect(sum of all proper divisors equals to the number itself). During
iterations the accumulator <code><?xxe-sn 26yv439af40 ag?>x</code>
assumes values as follows: 2, 3, 4, 5, 6, 6... After the first perfect
number is found, no further iteration will change the result anymore
since there is no increment, so the loop continues to go through the
same number again and again, making this an infinite loop. Obviously,
<code><?xxe-sn 26yv439af40 ah?>x=6</code>(the first perfect number) is a
fixed point in this example. It does not make any sense to continue
going through further iterations once a fixed point is reached because
the result is not going to be changed anymore, thus the loop can be
safely interrupted at this point.</para>
<para><?xxe-sn 26yv439af40 ai?>The compiler relies on manually provided
annotations to recognize when a fixed point is reached. There is a
special annotation <code><?xxe-sn 26yv439af40 aj?>final</code> reserved
to specify a fixed point for loops. Once an expression that marked as
<code><?xxe-sn 26yv439af40 ak?>final</code> gets evaluated it's assumed
that a fixed point is reached or in words the compiler knows it's the
very last iteration after which loop can be terminated safely. The
correct code for the example above is:</para>
<programlisting xml:id="LoopStatement2"><?xxe-sn 26yv439af40 al?>name="tests/ast.cpp: AST.Doc_LoopStatements"
//a loop exits after the first perfect number is found
answer2 = loop (2-&gt;x) :: int
{
if(IsPerfect(x))::int {x:: int; final} else {x+1}
}.</programlisting>
<para><?xxe-sn 26yv439af40 am?>In this case the compiler is able to
recognize that a fixed point is reached in order to know when it is safe
to terminate the loop. In the example, the final result <code><?xxe-sn 26yv439af40 an?>answer2</code>
is <code><?xxe-sn 26yv439af40 ao?>6</code>.</para>
</section>
<section>
<?xxe-sn 26yv439af40 ap?>
<title><?xxe-sn 26yv439af40 aq?>LOOP FOLD Statement</title>
<synopsis><?xxe-sn 26yv439af40 ar?>SYNTAX:
**loop fold (** //list// **-&gt;** //element//:: //type// [; //annotations//], //init-value// **-&gt;** //accumulator//**)**:: //type// [; //annotations//]
//loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 as?>
<listitem>
<?xxe-sn 26yv439af40 at?>
<para><?xxe-sn 26yv439af40 au?><emphasis><?xxe-sn 26yv439af40 av?>list</emphasis>
Container to iterate over.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 aw?>
<para><?xxe-sn 26yv439af40 ax?><emphasis><?xxe-sn 26yv439af40 ay?>element</emphasis>
Identifier that assumes value of a currently processing list
element.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 az?>
<para><?xxe-sn 26yv439af40 b0?><emphasis><?xxe-sn 26yv439af40 b1?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 b2?>annotations</emphasis> Expression
types and optional annotations delimited by semicolon.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 b3?>
<para><?xxe-sn 26yv439af40 b4?><emphasis><?xxe-sn 26yv439af40 b5?>init-value</emphasis>
Accumulator's initial value loop starts from.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 b6?>
<para><?xxe-sn 26yv439af40 b7?><emphasis><?xxe-sn 26yv439af40 b8?>accumulator</emphasis>
Identifier that assumes loop-body evaluation result after each
iteration.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 b9?>The <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw87?>loop fold</code>
statement is a commonly used particular instance of <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw85?>loop</code>
to Iterate over <emphasis><?xxe-sn 26yv439af40 ba?>list</emphasis> in
order to accumulate the result by applying the <emphasis><?xxe-sn 26yv439af40 bb?>loop-body</emphasis>
transformation to each <emphasis><?xxe-sn 26yv439af40 bc?>element</emphasis>
and an intermediate <emphasis><?xxe-sn 26yv439af40 bd?>accumulator</emphasis>.
The result of a current iteration is used as the <emphasis><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8b?>accumulator</emphasis>
value for a next iteration. Accordingly, the overall loop value equals
that of <emphasis><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8c?>accumulator</emphasis>
after the last iteration. If a fixed point is found evaluation
terminates earlier.</para>
<para><?xxe-sn 26yv439af40 be?>Example shows a code excerpt that looks
for the minimal element in a given list(and less then the initial value
<code><?xxe-sn 26yv439af40 bf?>10</code>):</para>
<programlisting xml:id="FoldStatement1"><?xxe-sn 26yv439af40 bg?>name="tests/ast.cpp: AST.Doc_LoopStatements"
numbers = {4, 8, 7, 1, 5}:: [int].
min = loop fold(numbers-&gt;x:: int, 10-&gt;acc):: int
{
if (acc &gt; x):: int {x} else {acc}
}.</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 bh?>
<title><?xxe-sn 26yv439af40 bi?>LOOP MAP Statement</title>
<synopsis><?xxe-sn 26yv439af40 bj?>SYNTAX:
**loop map (**//list// **-&gt;** //element// :: //type// [; //annotations// ] ) :: //type// [; //annotations// ]
//loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 bk?>
<listitem>
<?xxe-sn 26yv439af40 bl?>
<para><?xxe-sn 26yv439af40 bm?><emphasis><?xxe-sn 26yv439af40 bn?>list</emphasis>
Container to iterate over.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 bo?>
<para><?xxe-sn 26yv439af40 bp?><emphasis><?xxe-sn 26yv439af40 bq?>element</emphasis>
Identifier that assumes value of a currently processed list
element.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 br?>
<para><?xxe-sn 26yv439af40 bs?><emphasis><?xxe-sn 26yv439af40 bt?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 bu?>annotations</emphasis> Type and
optional annotations delimited by semicolon.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 by?>The <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw84?>loop fold</code>
statement is a commonly used particular instance of <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw83?>loop</code>
to Iterate over <emphasis><?xxe-sn 26yv439af40 bz?>list</emphasis> and
applying the <emphasis><?xxe-sn 26yv439af40 c0?>loop-body</emphasis>
transformation to each element. The result is a list that consists of
all the transformed elements.</para>
<para><?xxe-sn 2evpzktyvg7 -wunr7fl0rw8a?>An example below demonstrates
creating the <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw89?>even_number</code>
list by multiplying by 2 every element of <code><?xxe-sn 2evpzktyvg7 -wunr7fl0rw88?>odd_numbers</code>:</para>
<programlisting xml:id="MapStatement1"><?xxe-sn 26yv439af40 c1?>name="tests/ast.cpp: AST.Doc_LoopStatements"
odd_numbers = {1, 3, 5}:: [int].
even_numbers = loop map(odd_numbers -&gt; number:: int) :: [int]
{ 2 * number }.</programlisting>
</section>
</section>
<section>
<?xxe-sn 26yv439af40 c5?>
<title><?xxe-sn 26yv439af40 c6?>Types</title>
<para><?xxe-sn 26yv439af40 c7?>Primitive Types:</para>
<informaltable>
<?xxe-sn 26yv439af40 c8?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 c9?>
<colspec colwidth="173*"><?xxe-sn 26yv439af40 ca?></colspec>
<colspec colwidth="827*"><?xxe-sn 26yv439af40 cb?></colspec>
<tbody>
<?xxe-sn 26yv439af40 cc?>
<row>
<?xxe-sn 2ey6qxf8um8 1?>
<entry><?xxe-sn 2ey6qxf8um8 2?><code><?xxe-sn 2ey6qxf8um8 7?>bool</code></entry>
<entry><?xxe-sn 2ey6qxf8um8 8?>Booleans.</entry>
</row>
<row>
<?xxe-sn 2ey6qxf8um8 3?>
<entry><?xxe-sn 2ey6qxf8um8 4?><code><?xxe-sn 2ey6qxf8um8 9?>i8</code>,
<code><?xxe-sn 2ey6qxf8um8 a?>i32</code>, <code><?xxe-sn 2ey6qxf8um8 b?>i64</code></entry>
<entry><?xxe-sn 2ey6qxf8um8 c?>Signed integers; 8, 32, 64 bit wide
respectively.</entry>
</row>
<row>
<?xxe-sn 2ey6qxf8um8 5?>
<entry><?xxe-sn 2ey6qxf8um8 6?><code><?xxe-sn 2ey6qxf8um8 f?>int</code>,
<code><?xxe-sn 2ey6qxf8um8 g?>num</code></entry>
<entry><?xxe-sn 2ey6qxf8um8 d?>Currently <code><?xxe-sn 2ey6qxf8um8 e?>i32</code>
aliases. Reserved as placeholders for an auto detected appropriate
integral type and for auto detected appropriate either integral of
floating-point type, respectively.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 ci?>
<entry><?xxe-sn 26yv439af40 cj?><code><?xxe-sn 26yv439af40 ck?>float</code></entry>
<entry><?xxe-sn 26yv439af40 cl?>Double precision floating-point
numbers.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 cz?>
<entry><?xxe-sn 26yv439af40 d0?><code><?xxe-sn 26yv439af40 d1?>string</code></entry>
<entry><?xxe-sn 26yv439af40 d2?>Currently null terminated ANSI
char string. Reserved to be generic type with no particular
implementation. A concrete implementation is to be determined
similarly to the <link
xlink:href="/d/concepts/containers/"><?xxe-sn 2ey6qxf8um8 h?>containers</link>
approach.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 d3?>
<entry><?xxe-sn 26yv439af40 d4?><code><?xxe-sn 26yv439af40 d5?>*</code></entry>
<entry><?xxe-sn 26yv439af40 d6?>An unspecified type. Postpones
type checks for this expression. Examples: <code><?xxe-sn 26yv439af40 d7?>x = {amount=200, currency="USD"}::*.</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para><?xxe-sn 26yv439af40 d8?>Compound types:</para>
<informaltable>
<?xxe-sn 26yv439af40 d9?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 da?>
<colspec colwidth="312*"><?xxe-sn 26yv439af40 db?></colspec>
<colspec colwidth="688*"><?xxe-sn 26yv439af40 dc?></colspec>
<tbody>
<?xxe-sn 26yv439af40 dd?>
<row>
<?xxe-sn 26yv439af40 de?>
<entry><?xxe-sn 26yv439af40 df?>[ <emphasis><?xxe-sn 2ey6qxf8um8 j?>element-type</emphasis> ]</entry>
<entry><?xxe-sn 26yv439af40 di?>List of elements of the same type
<emphasis><?xxe-sn 26yv439af40 dj?>element-type</emphasis>.
Examples: <code><?xxe-sn 26yv439af40 dk?>x = {1, 2, 3}:: [int]</code>
- list of <code><?xxe-sn 26yv439af40 dl?>int</code>'s. Lists can
have different internal implementations.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 dm?>
<entry><?xxe-sn 26yv439af40 dn?>{<emphasis><?xxe-sn 2ey6qxf8um8 k?> key</emphasis>:: <emphasis><?xxe-sn 2ey6qxf8um8 l?>type</emphasis>, ... }</entry>
<entry><?xxe-sn 26yv439af40 dr?>Record: a list of elements of
different types possibly with named keys. Examples:
<code><?xxe-sn 2ey6qxf8um8 15?>{int, string}</code>,
<code><?xxe-sn 2ey6qxf8um8 16?>{name::string, age::int}</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 du?>
<entry><?xxe-sn 26yv439af40 dv?>variant {<emphasis><?xxe-sn 2ey6qxf8um8 m?>option</emphasis> :: {<emphasis><?xxe-sn 2ey6qxf8um8 n?>type</emphasis>, ...}, ...}</entry>
<entry><?xxe-sn 26yv439af40 dz?>ADT type. Variables of this type
can hold value of any type out of a list of permitted ones.
Examples: <code><?xxe-sn 26yv439af40 e0?>variant {FullAddress:: {string, string, string}, ShortAddress:: {string}}</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 e1?>
<entry><?xxe-sn 26yv439af40 e2?>slave <emphasis><?xxe-sn 2ey6qxf8um8 o?>identifier</emphasis></entry>
<entry><?xxe-sn 26yv439af40 e5?>Denotes a type constructed by
Transcend. See <link xlink:href="#slave-types"><?xxe-sn 2ezs03nkiyo 17?>slave
types</link>. An example: <code><?xxe-sn 26yv439af40 e6?>slave unit_test</code>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para><?xxe-sn 2ey6qxf8um8 p?>Type operations:</para>
<informaltable>
<?xxe-sn 2ey6qxf8um8 q?>
<tgroup cols="2">
<?xxe-sn 2ey6qxf8um8 r?>
<colspec colwidth="115*"><?xxe-sn 2ey6qxf8um8 17?></colspec>
<colspec colwidth="885*"><?xxe-sn 2ey6qxf8um8 18?></colspec>
<tbody>
<?xxe-sn 2ey6qxf8um8 s?>
<row>
<?xxe-sn 2ey6qxf8um8 t?>
<entry><?xxe-sn 2ey6qxf8um8 u?><emphasis><?xxe-sn 2ey6qxf8um8 v?>type</emphasis> [ <emphasis><?xxe-sn 2ey6qxf8um8 w?>key</emphasis> ]</entry>
<entry><?xxe-sn 2ey6qxf8um8 x?>Index operation: accessing elements
of a compound type. Examples: <code><?xxe-sn 2ey6qxf8um8 y?>Bio = type {birth_year:: int, name:: string}. YearBirth = type Bio[birth_year].</code></entry>
</row>
<row>
<?xxe-sn 2ey6qxf8um8 z?>
<entry><?xxe-sn 2ey6qxf8um8 10?><emphasis><?xxe-sn 2ey6qxf8um8 12?>type</emphasis> ( <emphasis><?xxe-sn 2ey6qxf8um8 13?>parameters</emphasis>... )</entry>
<entry><?xxe-sn 2ey6qxf8um8 11?>Constructs a concrete type with
the given parameters. Examples: <code><?xxe-sn 2ey6qxf8um8 14?>MyTree = type Tree(int)</code>.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para><?xxe-sn 26yv439af40 ee?>New types are defined as follows:</para>
<synopsis><?xxe-sn 26yv439af40 ef?>SYNTAX:
//type-name// = **type** (//parameters//...) //type-definition// .</synopsis>
<para><?xxe-sn 26yv439af40 eg?>Examples:</para>
<programlisting xml:id="Types1"><?xxe-sn 26yv439af40 eh?>name="tests/ast.cpp: AST.Doc_Types"
Tuple = type {string, int}.
Int = type Tuple[1]. //accessing by index
List = type(X) [X]. // List of elements of type X.
IntList = type List(int). // type function to construct List of ints.</programlisting>
<section>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8v?>
<title><?xxe-sn 2f0cduzin5j -wunr7fl0rw8u?>Slave Types</title>
<synopsis><?xxe-sn 2f0cduzin5j -wunr7fl0rw8t?>SYNTAX:
**slave** //predicate//
</synopsis>
<itemizedlist>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8s?>
<listitem>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8r?>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8q?><emphasis><?xxe-sn 2f0cduzin5j -wunr7fl0rw8p?>predicate</emphasis>
Name of a logic predicate</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8o?>Slave type is a reference to a
type defined on the Transcend side. This gives Transcend a full control
over program types marked as <code><?xxe-sn 2f0cduzin5j -wunr7fl0rw8n?>slave</code>
ones. The type is constructed in such a way that variables of this type
are able to hold <emphasis><?xxe-sn 2f0cduzin5j -wunr7fl0rw8m?>predicate</emphasis>'s
arguments. Type inference works as follows:</para>
<itemizedlist>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8l?>
<listitem>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8k?>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8j?>If a predicate has only
one argument then a constructed type is a type of this argument:
<code><?xxe-sn 2f0cduzin5j -wunr7fl0rw8i?>int</code>,
<code><?xxe-sn 2f0cduzin5j -wunr7fl0rw8h?>string</code>, variant or
tuple.</para>
</listitem>
<listitem>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8g?>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8f?>A constructed type is a
record in case of several arguments.</para>
</listitem>
<listitem>
<?xxe-sn 2f0cduzin5j -wunr7fl0rw8e?>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8d?>Predicates correspond to
variants in a constructed type.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8c?>An example; Transcend
facts:</para>
<programlisting><?xxe-sn 2f0cduzin5j -wunr7fl0rw8b?>person("John", 1962).
person("Bill", 1961).</programlisting>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw8a?>The Brute side:</para>
<programlisting xml:id="SlaveTypes1"><?xxe-sn 2f0cduzin5j -wunr7fl0rw89?>name="tests/transcend.cpp: Transcend.Doc_SlaveTypes1", lines=15
PersonNative = type {string, int}.
Person = type slave person.</programlisting>
<para><?xxe-sn 2f0cduzin5j -wunr7fl0rw88?>In the example above the types
<code><?xxe-sn 2f0cduzin5j -wunr7fl0rw87?>PersonNative</code> and
<code><?xxe-sn 2f0cduzin5j -wunr7fl0rw86?>Person</code> are
equivalent.</para>
</section>
</section>
<section>
<?xxe-sn 2ey6qxf8um8 19?>
<title><?xxe-sn 2ey6qxf8um8 1a?>Variants</title>
<para><?xxe-sn 2ey6qxf8um8 1b?>Sometimes it is useful for a variable to
have an ability to hold values of different types depending on some
conditions, in other words to have a <emphasis><?xxe-sn 2ey6qxf8um8 1c?>variant
type</emphasis>. An example:</para>
<programlisting xml:id="Variants1"><?xxe-sn 2ey6qxf8um8 1d?>name="tests/ast.cpp: AST.Doc_Variants1"
Color = type variant {
White, Black, Magenta,
- CustomColor:: {r:: int, g:: int, b:: int}
+ CustomColor(r:: int, g:: int, b:: int)
}.
draw = function:: int
{
clrBorder = Black():: Color.
clrBackground = CustomColor(50, 50, 50):: Color.
drawRectangle({0, 0, 100, 100}, clrBorder, clrBackground)
}</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 ei?>
<title><?xxe-sn 26yv439af40 ej?>SWITCH VARIANT Statement</title>
<synopsis><?xxe-sn 26yv439af40 ek?>SYNTAX:
**switch variant** ( //condition// [**-&gt;** //alias// ] [:: //type// [; //annotations//... ] ] ) :: type [; annotations... ]
[ **case** ( //guard// ) //case-branch// ]...</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 el?>
<listitem>
<?xxe-sn 26yv439af40 em?>
<para><?xxe-sn 26yv439af40 en?><emphasis><?xxe-sn 26yv439af40 eo?>condition</emphasis>
Expression of a variant type.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 ep?>
<para><?xxe-sn 26yv439af40 eq?><emphasis><?xxe-sn 26yv439af40 er?>alias</emphasis>
Identifier to denote unwrapped content of the <emphasis><?xxe-sn 2ey6qxf8um8 1e?>condition</emphasis>
expression withing case branches.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 es?>
<para><?xxe-sn 26yv439af40 et?><emphasis><?xxe-sn 26yv439af40 eu?>guard</emphasis>
Name of a variant to match against actual condition's variant.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 ev?>
<para><?xxe-sn 26yv439af40 ew?><emphasis><?xxe-sn 26yv439af40 ex?>case-branch</emphasis>
Code block to execute in case of the matched variant. The
<emphasis><?xxe-sn 2ey6qxf8um8 1f?>condition</emphasis> expression's
content is referred to by <emphasis><?xxe-sn 2fadpf0i3zr -wunr7fl0rw8t?>alias</emphasis>
within the branch.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 ey?>Variant variables require special means to
test which exactly variant they contain at any given moment as well as to
access it. Usually, languages that support variant types(ADT) solve this
problem be means of <emphasis><?xxe-sn 2ey6qxf8um8 1g?>pattern
matching</emphasis>. Xreate intentionally does not support pattern
matching since it is depends on parameters order, which is plainly
unacceptable; besides, it's hardly usable in case of a large amount of
parameters. Instead, Xreate supports special syntax to <emphasis><?xxe-sn 2ey6qxf8um8 1h?>unwrap</emphasis>
a variable's content using <code><?xxe-sn 2ey6qxf8um8 1i?>switch variant</code>
statement.</para>
<para><?xxe-sn 26yv439af40 f0?>An example:</para>
<programlisting xml:id="VariantsSwitch1"><?xxe-sn 26yv439af40 f3?>name="tests/ast.cpp: AST.Doc_VariantsSwitch1",lines=15
Month = type variant {
- MonByName :: {name:: string},
- MonById :: {id:: int}
+ MonByName (name:: string),
+ MonById (id:: int)
}.
nextMonth = function(month:: Month):: Month
{
switch variant(month):: Month
case (MonByName)
{
monthName = month["name"]:: string. //here month has {name:: string} type
MonByName(nextMonthByName(monthName))
}
case (MonById)
{
monthId = month["id"]:: int. //here month has {id:: int} type
if(monthId == 11):: Month
{ MonById(0) }
else
{MonById(monthId + 1)}
}
}</programlisting>
<para><?xxe-sn 26yv439af40 f4?>The function <code><?xxe-sn 2ey6qxf8um8 1j?>nextMonth</code>
computes the next month after a given one. The parameter <code><?xxe-sn 2ey6qxf8um8 1k?>month</code>
can't be directly accessed due to being of a variant type; hence, It
should be <emphasis><?xxe-sn 26yv439af40 f8?>unwrapped</emphasis> before
using. As seen in this example, Xreate silently defines a new variable
with the same name <code><?xxe-sn 2ey6qxf8um8 1l?>month</code> which holds
an unwrapped content for each <code><?xxe-sn 2ey6qxf8um8 1m?>switch variant</code>'s
branch independently.</para>
</section>
<section>
<?xxe-sn 2fds09lgw74 m?>
<title><?xxe-sn 2fds09lgw74 n?>Versions</title>
<synopsis><?xxe-sn 2fds09lgw74 o?>//identifier// [**{** //version// **}**]</synopsis>
<itemizedlist>
<?xxe-sn 2fds09lgw74 p?>
<listitem>
<?xxe-sn 2fds09lgw74 q?>
<para><?xxe-sn 2fds09lgw74 r?><emphasis><?xxe-sn 2fds09lgw74 s?>version</emphasis>
Number to specify the identifier's version.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2fds09lgw74 t?>Versions is a language construct to deal
with mutable data. An example: </para>
<programlisting xml:id="Versions1_1"><?xxe-sn 2fds09lgw74 v?>name="tests/ast.cpp: AST.Doc_Versions1"
Date = type {year:: int, month:: string}.
test = function:: Date; entry
{
x{0} = {year = 1953, month = "March"}:: Date.
x{1} = x{0} + {month = "February"}:: Date. //updates a single record's field
x{1} //returned value
}</programlisting>
<para><?xxe-sn 2fds09lgw74 w?>In the example above <code><?xxe-sn 2fds09lgw74 x?>x{0}</code>,
<code><?xxe-sn 2fds09lgw74 y?>x{1}</code> are different versions of the
same variable. This is a simple trick with the idea that for all intents
and purposes <code><?xxe-sn 2fds09lgw74 z?>x{0}</code>, <code><?xxe-sn 2fds09lgw74 10?>x{1}</code>
behave like different variables but really aren't. All analyses treat them
as different immutable variables, yet the compiler actually uses the same
memory address for them making this an update of a variable. It is a hint
from a developer that the only one version of a variable should be
available at any given time. The only analysis that knows the truth is the
versions analysis. It is responsible for code validation in order to make
sure that there is no expression that uses an outdated/unknown/unreachable
variable's version. An another (counter)example:</para>
<programlisting xml:id="Versions1_2"><?xxe-sn 2fds09lgw74 11?>COUNTEREXAMPLE, name="tests/ast.cpp: AST.Doc_Versions1"
x{0} = 8:: int.
x{1} = x{0} + 10:: int.
y = x{0} + x{1} :: int. //invalid code: uses several versions</programlisting>
<para><?xxe-sn 2fds09lgw74 12?>The versions analysis builds a variables'
liveliness graph to track versions usage and reveal situations when it's
impossible to compute an expression due to the fact that it refers to an
(possibly) outdated or unreachable version.</para>
</section>
<section>
<?xxe-sn 2ey6qxf8um8 1t?>
<title><?xxe-sn 2ey6qxf8um8 1u?>Records</title>
<para><?xxe-sn 2ey6qxf8um8 1v?>Record's elements(fields) are denoted by
strings in order to access the field's value. This gives a possibility to
use variables to reference fields. Such references are statically resolved
during <link xlink:href="/d/concepts/interpretation/"><?xxe-sn 2ey6qxf8um8 1w?>Interpretation</link>.
An example:</para>
<programlisting xml:id="RecField1"><?xxe-sn 2ey6qxf8um8 1x?>name="tests/ast.cpp: AST.Doc_RecField1"
Employee = type {
name :: string,
surname :: string,
signature:: string
}.
test = function:: string; entry
{
employee = getAnyEmployee():: Employee.
primaryKey = "surname":: string.
employee[primaryKey]
}</programlisting>
<para><?xxe-sn 2ey6qxf8um8 1y?>In Xreate the left side of any assignment
is always an identifier, hence there is special syntax to update one(or
more) record's fields. An example:</para>
<programlisting xml:id="RecUpdate1"><?xxe-sn 2ey6qxf8um8 1z?>name="tests/ast.cpp: AST.Doc_RecUpdate1"
Day = type {
year:: int,
month:: string,
day:: int
}.
test = function:: Day
{
tomorrow
today = {year = 1936, month = "July", day = 21}:: Day.
tomorrow = today + {day = 22}:: Day.
}</programlisting>
</section>
</chapter>
<?xxe-revisions
#12 2019-05-18T10:27:21Z pgess
#11 2019-05-16T15:13:16Z pgess
1sPEAAABgrx7AB6CqmEAAA0Kc4KgXyMMExVzDFOJVQCCpF+8GXuB9w0=
#10 2019-05-14T16:34:55Z pgess
1sPEAAABgqphAIIggqpoAAaBG3dBQUFBQWJzv1AjBCMEE4RkgwQTCmOBOgEBE2xTiFwBATMHQwdj
CmMMQwkzNlOhIiMFY4FBAQFDB0OMaRMEYw1jgSeTDlObCxMEM4Eokw5jBlODUoMEQwtDgTYjGzOO
fHMEU4EoczczgVoBAVMKEwkTY1O5bmMOU5h0gwUzgSmTDlOCDIMOMwczgUEBARMHEwUTBGOBADMH
/FMEYwQzBTOaMwDNRoGSNL9Ua7sthG6Nd4IllD7zLaMjhFm1Io50iz6BhXChJLgGgUe6Y65QjHdj
gTK3apsNY4lggTlrjBWDXYUrgU7qjn5ogVyTGbBmjgCCT4GjFLl4RJh2Y4E0MYJCgh3EPLFuiV2B
TYGnTJAbgZsahG2bCYkd
#9 2019-05-11T15:02:16Z pgess
1sPEAAABgqpoAD+CqnAAAB8Zc4H2HhMEE4IfQwRTgUFDCWMFgwSDEBMWQxBTEDOwEgCB/lCB9iCe
IoIhjnGFA1BBhiuDdtNXghU=
#8 2019-05-11T12:29:03Z pgess
1sPEAAABgqpwACuCmDkAABQQc4HfExMNQ44+Ex9DCxMVIwwzqhAAqyWBs26pSIGWIoNAIb8Z
#7 2019-05-10T16:50:38Z pgess
1sPEAAABgpg5ABaCl1YAAAkGc4HefRMlQ7g0AKcLgbh6
#6 2019-05-09T19:09:59Z pgess
1sPEAAABgpdXAItQgfpzAGWGFYRNIGNjY2NtcHFjdGN1Y3gsIGljeS5QbW9VZz8+W2hvZHA6OnFy
ZHNkdCB3IGR4KGR5ej8+SGYgLCBlM2VlZWJjPz5laW8uIGFuZCBDV2l6TGVmaWo/PiJOID0oIkE1
ZmY3VjlmYmZzq2sTBkOmGVMEU95tAQFjjjETLUOBXGMMUyABARMEQxATCwEBQwZjCFMmAQFDBJMQ
gwsBAUMEMwozBjMOEw1TRTNwQwsjJxMEkxBjDAEBU00zDTMsEwUjHBMEkxBTDAEBUzYBAWMogywT
BCMdExSDC75TJYMLAQIzCmMEgyxDBIMdEwSTEIMLAQJjBAEDQwRDJoMLAQJjEQEBQyCDgSi7YwYT
BDMEYyVjBUMNvhMEMwdjBkMGYyxDdwEBQxETCEMdUwRDBEMLEwdjgzFzHQEEQyIBAUMaEwSTB2Ml
M2tDE4MLMwRDBXMJYzeTUHMdAQFjGIMLAQJDEQECgyIBAVMUMwQjLwEBEwRTEjMOUzaDCwECYyqD
CwECQxABAWMRM1BzHQEBQwkBAVMWgwsBAmMUUwQBAVMgAQJzFIMFIzTGQwhDB1MFUwXfUwgTCmMG
UzQBAUMOUwpzBhMJAQJTDnMIUwozUCMcAQJDB2MhoxMJUw6TB3MpYwRTDDMMIwlzE2MMYwhTBDMO
kywTIAEBEwSTEGMMEwRTIFMFUwYzBTMNIyIBApMRcwSTB3MmAQNDBVMRMxZzE4MLAQFTBAECQwkz
DCMEMwZTCgECUwRzCFMpEyQzKRMIAQFDC2MfU4EBYwpTgSJDPDMlQwUTBQEDUw9DBGMEUwUTCJMf
YzFTBWOCMVMLEwRDCzM1M1lTKkMJY4ElEwQjDRMQEwdTE5OBFGMkQwUzDAEBUyQBAWMQQwQTBxMM
YxCDG0MEQy4zBCMFgxBjLdUjIQEBYxsjCYMbUwS+EwUjBGMIYwQjBlMEIxwBAjMQgwRzCyMewiMI
EwozLYMLQykBAWMdUwUzBTMPpCMEMwkzEoMFYwUTBbIzBAEDUwVDBIMFUwSDBWM0gwiTHgEBgxBj
BEMHEwUzBpMcAQFzBEMNEwWTEIMLAQIjDYMHsGMGQwwzCBMFQ1IzECMdAQFTCDMSUwSDBBMIQwUT
BFMPgxsBAUMEMw1jBlMEEwcjHgEBQxNjDZMKUxETFNMzWpMFMwZDBCMEEwcTBDMFUwQjBkMhYwsA
qnuBBoGAJqYbhGSPKY5fiimCFY0Qi1eDNFP0Q8xS3kGVtMxa0xi5M4MZ2TpNVI0bgjbOS5U7Dfh0
gjTPD4FIuQWV+XYNN/O6QIFNnRG0kQKBlAK0l0WZQvOPBPCEfpW0gaYngSFZtDIS84GMU64hhByp
f5EljRgIrxy4NrxllBfZO4cq2DZ7gatJJGPHIwqBniwT9YQ9g1WMOZWKIkOFa7SBCoGbZdgnAPVO
tIxhCb5yhn2DYYpykQOJd4HDM7RDtDcSEvVOiFu0Lbc2oQgmhoNkkH+6JL1PwgKleo1AoV2EHqxI
HzaOal6B2GUttRcLkyROrQP/cIVw7XCVK8sfjSm/F5ACJJEzgUjGTg2ap2+PV5WeFINAgdo/zif4
W7ooiA+NYK85lSuHZ4VXEyS0tE6xV4GdaptuwVahaSbsFKkkg0KFfYG2fIVgaIVWgQziCYg+7V/B
ESWOJItgjnuDRN2MS/IwOqJUiUqCRYN2QVyBd3KB2CuCevMi3VaiJmWBFpVOLVgl9mjdeIY1g2z4
gZ9+gZACr1SDL2lbmQCRGFmBfPiUCLVAjnOuQPsahzaHbuVekkKBjgbKbz6OTZIQi1OB5Au0lC46
9WRGMIQfl3mB7HuvRbwclSwSgT4MtlG8nGisgwfFtA2ScYR2lFmBsxdzo4J0gYM8lbSxWlaGIYGD
Ca4zjR2tZjyEU4E5yDiBGq8OpdQtmA6ILK1M+LhZvlAOzQKoFIEfzkKcTtOBqAiDK6d8mDZ6gQiJ
YQHpAeE6gZAGjG+GVoGREZFW
#5 2019-05-09T12:03:54Z pgess
1sPEAAABgfpzACWB+mcAABMLc9olIwUTI1OOcWOBRTNEQ4GPIADkTdoqJY51gUlG
#4 2019-05-07T18:27:55Z pgess
1sPEAAABgfptAIxXgeQoAEuGeYUKYXBwYW9uYnVpbHQtaW5yZWN1cnN2dGFraXIuIEFsc3IrR3Mu
IFBkYWwvL0lGUyAvL1JXaGlsaXVuZG9ub2hpYXh5aW5wdWMyM2M0c4ohExRDC0MEExBzCyMEIwRT
BEMIQwQTBWMGAQQTBRMEvfxDBFMNAQhDB2MOAQYzBFMMMwpjBgEBYwgTFlOQFGMMY40pM5BEIwRj
CGMEUzNTBFOBcGMEQwUTBzM1Y1wTBEMMY4FtkwSTDDMUIwZjgRdDL4OBFBMqYxWTEGM2YwtjKyMF
AQMzBEMMUwUTBmMFAQIzBAEFMwRjBxMKQwsTZjMFEwgBAUOBJDMlYwpTClMhUwljgQ8BAVOBOGMH
gwpjgU7fQwhTBoMKEzVjYkMEMxBTGnMVkxCDG2MEYzYzBTMGM19jTFMMMx9TQxMGAQRjNEMPU2Yj
BxMGAQFjBgECYwdDSmMHQxxTE2MbMwgTBlMHcwRjBTMEQ0djCYMbYwRTKJMIMw6DGkM5Y1ozEUMg
U4E3YydzCpMHQyozgUdjBkMJ8DOBGwECM4UagxMjBUMmUxEzgWdTDRMFMxBTFnM1U1kzREOBJyMH
Ux5zFZMQgxszBFMHMwozH2NLM2KTKEOBPwEBYwgBAVMKIwYTBUMhg1JjNGMEQ2mDBzMKAQIzBzMQ
gwQzgV1jHlM1U19DOXMVkxBTdjMGEwZDT1MHMxEBAWMFQwhTIVMvU1oTBGNbEwVDF2MVMwRTBzMK
Yz0zBkMWEwozgQAzHmMFQ4FNAQQTBBMFYwQzCmNWMwQzBwEB+xMEkwZDB1MJu1MQAQITBUMHkwZj
JFMIQw0TBGMgQzhTBlMdMwkBAiMHMzJDDxMKcwTTQx8jJTMEIxNTMDMhEwdDOmMLMxwTC0NVUwUj
DlMFUwczBjM9EwSTBEOBHXMEMw2TBnMHMxATB0OBEVMJYxIzBXMWQwYBASMIEwYTBhMEMwRTJlMK
Qx9TgTeTBhMEYw9DB2MNUxQzKoMEM4FZUwtDB3OBEEMhUxFjD3M1Y4EVkwtTNTOBE0MoEwRTgRQz
CzM4YxUTEIMbUwRTByMGY01DE1MhU2wzShMEcwkTBBMHIwtjBTMFMxhDBIMVQwUTBCMFQwczQTMc
AQFDFFMEUxljOYMhQ4MfIyJjBGOBfnMLgwdTgRBzIYMRcw+TNTOBFVMFcwRzCTM4QyBTBGMcEwQz
IAEBMxdzFZMQIxwBAWMQAQRTIkMdgwQjIFM6IwdDIGMeExYzgRqTBWMGMwVTMYMbAQIjCUMXUx0B
AUNREwsBAmMVcwtTCkO8UQCFAo01hU6DdDe5Z/QEmjzLAIMXuW2XHJRuhg+8KIMExR+BLaEiL8NA
qXgqhxYRhiuDdpd2khyKItFglReDYJBcjmQ7rFTKYqgUhxCXeIVkYA3kbIF/600dgRtgjXiudSGB
ZpRuQ8hasSxCjzXCTp8smBa8c7ZO0nmDGcgHuGiJQ3mBJYsmo0mdeZMqkmKBEs5D7YFJgTTJZY1g
7cRgi0FKZhHVIfRbesRjgwlAYYEDgTIjsFZbSCLWfYtIkQ2BPMxPgkkJNRcoiUSoVQ+pAYJygTni
VPSBMo11E6UAlJFRQ4JnD4IOgUDVK4ZNeekOhg35gWKBHYiKcYU2dDuGWLEIpGSCCdVMW0X0CYEu
1SH0X+QPj3JMI0/6gQ2BRYFI7w2VLAoi0WKpU4JWiKRKjAyBB/kYmGeeTII2YtUhX55OhCSBCK1x
V6RMn12ZTkAxx11hqmtrI+gIjB8kDpBN2WeLU2SBA/IkJbVOo0flaMg0jHfPFVmGGrdy7YYqgmKe
EIFqtVcVbxGmZzKJYBc+rCZYgnqpVTiZWrlkD4F81WSpblOIERsy4ygqQw2uIS/hCYN+rDsVg18K
t3FVXcyBI+0XgVPseIlemXCBIYl5aNdGjXmBi1P7MIV61h+MIN9ltgBQsIRi+RChQbg+P5xK+TKB
ZcBwY4ETI5V+Y1chgSA2gReWKS3IcYEn3SyKIfR5gTWcEwxRjkM4b+BKv7llhBeZXudFy0gtpHpa
jCTpeMc3nFaZBEMfLxYEYlqSTqxjg0VTaYIa9hkXUEWmCQ9Wh3GBgg+bfYF7hH6BiAPaMdUhkBod
6HjFMYGBUkavC0Uksm2COvePA4h8gS30u36kWotSRIM0aSvgeIIf
#3 2019-02-23T12:37:01Z pgess
1sPEAAABgeQqAIgmgeMrAHyEMoJvNTM1NTVnLCwgaGlzaWNzOiBxdWU1NWssIGx0ZXJmYWNFeHRl
cm4tQzVvNXBxPz5POiwgVnN0T2lpbmZsdS4gc3c2Zz8+NSwgNnA/PissIC0sICosIDZ0LCAhPSwg
NnU2dywgIDcxID03Mi4gID0gIC0gICBoLmFzc29jZHOEEBMEEyQBAUMEIw0BARMZQwRTHNNjGgEB
MwVDGwECEwoBATMM5FMMIwiTHQEBUwQTCSMnAQFTBEMEAQljBEMpAQETBXMbAQJDDQECYw0jCHMd
AQEzFXMIcx1jBQEGEwQBCCMsYwVzGwECYzEBAkMGIyjEAQEjCquDC0MiMwRTHQEBIwmDCIMdAQEj
CiMnIwQjEBMlUwcTJVMEUxUzDkOBCFNIIwljTwEBQwUBAVMIIwpTBhMIQwkBBVMEMw1TBUMbYwlT
HlMLAQIjJUMEEwUBAUMaAQEzBFMEUwgzBkMMcwlzDGNgYwtThysTCwEHMxxTLFNcMwYTBkMqYwRj
JUMEQwQjCWMSIwUTBUM1gwQzJEMEUxITDIMEM4FsgwsBDWMJgyxDaIML4gEGQwgjBoMGIwQzBhMk
gwu+gwpjbYMLAQJjCQECQwYjCQEBUw+DWSMGEwtjJxMEM2pTCCMJQxODCwECQwgjBIMHIwhjDGMG
AQJzBmMGIwdTCpMGMwpjB4MTgwsBAlMGcwQjHQECQwQBA1MMIwhzK1OBBAEDQ4E7UwRTB3MJIzYz
CjN3MwUTDoMMUw1DSEMRUwtTBFMEgwsTCyMKEx9DKwEBUxcBAWM9Iw0jIaUjC2MNMwxjMhMEcwu9
Yw9jGgEFMwQBASMQkw4zNxMHM4EHUwZTIVMRM0pTCmMIEwRTL0MRUw9zBDMLM2VjUiMEM4IaIwlz
K1MkMwpDBkMTMwUzB2MEUxITBTOBq2MAkmGRICyvPYMnizOEFiQhICCMYA6HDr9DSdKdMo4XNc0J
r3S3I68FlX+xkEeDQjq5r3G5uasAoHKBYap2sYcRoSKBRo59pmsKK0m3RibGX5qan1wy5WyEXqkW
i0qDdIRuKhkRgRuCJVKBN8cZnm+nPYV9g0qCDqZHgW5LyA2BBGuBGt9nh3MIrSfJEhuvPQ8bNYNq
MWuDNIdjjQxJf4QYGK8eLJo9K6IWEL9dhBlL2zfSICqWSNsxtIJ46Ta0dFgKRBcHnzW0mhpEZbR6
M4FpEummAJEAgliGYY8qgXXRD40xtJAJ8QrZgmQeu08IHcgiDiUbnlsStCr1iiqTVjqpIYlAgQm4
QIFBZJ1YsSlYSI9gVhpiTOI0qSWoWjivb5sHjUueVSsX7XmKAKsignuXR3KCW5JxiJcbUxa5AUpQ
N64nZKZngSSBECGGd7k7jTdeoBl1cYF0JmnfSViqNTWCT6ATyU8ysFQZo3QPqkEe
#2 2018-12-18T15:50:51Z pgess
1sPEAAABgeMqAFCB4lUAASggLXObCwEBE4EIIx9DFRMsY4GNb0MjQyITB1MEY4FhcyNTBBMFIzdD
tF4Amw6BCYEpmU2BCIGXHoGOHowjjkUmXYgkgatoghiCZA==
#1 2018-12-18T15:11:23Z pgess
1sPEAAABgeJVADCB4lkAABkQc+xgE5kzQ5JQgwhTshozg19DkFhTCmODEwDsX5kyEZJXshmDXoYP
ilQ=
-?>
\ No newline at end of file
+?>
diff --git a/documentation/index.xml b/documentation/index.xml
index 6bd404c..e29172d 100644
--- a/documentation/index.xml
+++ b/documentation/index.xml
@@ -1,434 +1,434 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 2b06cb2u4g0 1?>
<title><?xxe-sn 2b06cb2u4g0 2?>Xreate Manual</title>
<para><?xxe-sn 2b06cb2u4g0 6?>Xreate is an open source general purpose high
level programming language designed to write efficient and safe computer
programs.</para>
<para><?xxe-sn 2b06cb2u4g0 8?>Here "high level" refers to the developer
oriented side meaning exactly an ability to easily write, read, reuse, as
well as adapt software to a constantly changing environment or business
goals. In this respect, any software product can be evaluated on the basis
of three dimensions: efficiency, safety, and flexibility. Unfortunately,
those properties are proved to be largely contradictory, for it is
manageable to write either efficient (yet unsafe) or safe (yet impractical)
code, but not both. Thus, the ultimate goal of the language is to allow
developers to produce code that would have all these properties at the same
time. Blending features of seemingly incompatible programming paradigms is a
basis of Xreate's design principles.</para>
<para><?xxe-sn 2b06cb2u4g0 7?>To achieve the aforementioned design goals,
Xreate consists of three distinctive layers:</para>
<itemizedlist>
<?xxe-sn 2b06cb2u4g0 e?>
<listitem>
<?xxe-sn 2b06cb2u4g0 f?>
<para><?xxe-sn 2b06cb2u4g0 g?><link xlink:href="/d/syntax/"><?xxe-sn 2b06cb2u4g0 o?>Brute</link>.
The lowest layer is called <emphasis><?xxe-sn 2b06cb2u4g0 p?>Brute
</emphasis>— this is code that is intended to be actually compiled. Code
on this level implements actual software functionality. It resembles the
usual imperative languages' apparatus and consists of executable
instructions such as arithmetic, branching, input / output, etc.</para>
</listitem>
<listitem>
<?xxe-sn 2b06cb2u4g0 i?>
<para><?xxe-sn 2b06cb2u4g0 j?><link xlink:href="/d/transcend/"><?xxe-sn 2b06cb2u4g0 q?>Transcend</link>.
Brute alone is not enough to constitute a full-fledged language since
code requires various non-executable metadata to express developer's
intents, check correctness, validity and perform other types of
analyses. In Xreate everything of this sort belongs to a declarative
type layer called <emphasis><?xxe-sn 2b06cb2u4g0 s?>Transcend</emphasis>.
Transcend is a logic reasoner that is appropriate to do management-type
work — it analyzes, oversees and controls Brute by guiding compilation
process. More precisely, everything on this level, logic or transcend
facts and rules, is gathered and sent to an external logic solver to
make solutions that are brought back in order to guide compilation.
Unlike usual static analysis tools, Transcend directly controls
compilation(see <link xlink:href="#basic-example"><?xxe-sn 2dc49lhpp1c 4?>Basic
Example</link>) and able to make decisions even based on data available
only at runtime(see <link
xlink:href="/d/transcend/late-transcend/"><?xxe-sn 2dc49lhpp1c 5?>Late
Transcend</link>)</para>
</listitem>
<listitem>
<?xxe-sn 2b06cb2u4g0 l?>
<para><?xxe-sn 2b06cb2u4g0 m?><link
xlink:href="/d/concepts/interpretation/"><?xxe-sn 2b06cb2u4g0 r?>Interpretation</link>.
There is also <emphasis><?xxe-sn 2b06cb2u4g0 t?>Interpretation</emphasis>
— the intermediate level resembling dynamically typed languages that is
used as a contact point and interpreter between Brute and Transcend. See
an <link
xlink:href="/d/concepts/interpretation/#querying-example-gui"><?xxe-sn 2fxwo1r89a8 r?>example</link>.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2b06cb2u4g0 u?>On a syntactic level, Xreate is a procedural
language with extensive use of <emphasis><?xxe-sn 2b06cb2u4g0 v?><link
xlink:href="/d/transcend/"><?xxe-sn 2b06cb2u4g0 w?>annotations</link></emphasis>
— arbitrary unconstrained metadata that a software developer can attach to
different language constructs, variables and code blocks. Annotations are
completely invisible for the compiler proper and used by Transcend more as a
suggestion conveying additional information.</para>
<remark><?xxe-sn 2ccp2iy80zj 1td6aqezxvj7l?>"a different language
constructs": если подразумевается "конструкции разных языков", тогда лучше
"different languages' constructs". Если конструкции языка, в целом, то тогда
артикль a не нужен</remark>
<para><?xxe-sn 2da0r0b6680 2?>There are several extensions already
implemented to give a feeling what does this structure can be used for.
<link xlink:href="/d/concepts/containers/"><?xxe-sn 2da0r0b6680 3?>Containers</link>
chapter describes that it is possible to reason about and automatically
choose the most appropriate data structure's implementation depending on how
it is used in the code. Look at the example below:</para>
<programlisting><?xxe-sn 2da0r0b6680 4?>x = [1, 2, 3]:: [int].</programlisting>
<para><?xxe-sn 2da0r0b6680 5?>Container <code><?xxe-sn 2da0r0b6680 6?>x</code>
does not have well defined implementation just yet. Only by looking how it
is used throughout the code, the compiler is able to decide how exactly to
store container's data.</para>
<para><?xxe-sn 2da0r0b6680 7?>Interaction of different components and joint
use of external resources is covered by <link
xlink:href="/d/exploitation/"><?xxe-sn 2da0r0b6680 8?>Exploitation</link>:</para>
<programlisting><?xxe-sn 2da0r0b6680 9?>logger = createFileLogger("/some/file"):: Logger.
...
write(logger, "First log entry").
...
write(logger, "Last log entry").</programlisting>
<para><?xxe-sn 2da0r0b6680 a?>Exploitation reasoning allows to determine
when it is the <emphasis><?xxe-sn 2dc0uidlnnk 1?>first</emphasis>,
<emphasis><?xxe-sn 2dc0uidlnnk 2?>last</emphasis> access to resources such
as files, in other words, it infers access order. As a result it is possible
to automatically initialize / destruct related resources. Unlike RAII, an
another related technique, Exploitation is reserved to manage resources
usage that spans across different parts of a program: modules, plugins,
etc.</para>
<para><?xxe-sn 2dc0uidlnnk 8?><link
xlink:href="/d/virtualization/"><?xxe-sn 2dc0uidlnnk 4?>Virtualization</link>
reasoning also helps to work with external resources by enabling access
control <emphasis><?xxe-sn 2dc0uidlnnk 5?>if and when it is needed
only</emphasis>. Example:</para>
<programlisting><?xxe-sn 2dc0uidlnnk 6?>openFile("/some/file"):: string; assign_sizo(zoneA).
openFile("/some/file"):: string; assign_sizo(zoneB).</programlisting>
<para><?xxe-sn 2dc0uidlnnk 7?>If the compiler recognizes file access from
the different zones, as in this example, it applies an appropriate
virtualization strategy enough to ensure that instructions that belong to
different zones do not interfere with each other.</para>
<para><?xxe-sn 2cdtco54w00 3?>Unlike "pure", academic languages, Xreate
targets safe and reliable usage of effectful computations such as IO that is
covered above as well as mutable structures described in the <link
xlink:href="/d/communication/"><?xxe-sn 2b3f3osfk74 l?>Communication</link>
chapter.</para>
<para><?xxe-sn 2dc49lhpp1c 2?>Note, that the described extensions are not
part of the compiler and developers can write their own custom transcend
rules to cover other aspects.</para>
<section>
<?xxe-sn 2b06cb2u4g0 3?>
<title><?xxe-sn 2b06cb2u4g0 4?>Basic Example</title>
<para><?xxe-sn 2b06cb2u4g0 5?>To demonstrate what Xreate is all about,
basic example is given below:</para>
<programlisting xml:id="Example_1"><?xxe-sn 2b06cb2u4g0 x?>name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15
guard:: iAmVeryFast
{
div = function(a:: int, b:: int):: int
{
a / b
}
}
guard:: iAmVerySafe
{
div = function(a:: int, b:: int):: int
{
if ( b == 0 ):: int { zeroDivisionErrCode() } else { a / b }
}
}
test = function:: int; entry; iAmVerySecure
{
div(10, 5)
}</programlisting>
<para><?xxe-sn 2b06cb2u4g0 y?>Here entry point of the program is a
function <code><?xxe-sn 2b06cb2u4g0 z?>test</code> recognized so by the
compiler because of annotation <code><?xxe-sn 2b06cb2u4g0 10?>entry</code>
in its signature. There are also two functions with the same name
<code><?xxe-sn 2b06cb2u4g0 11?>div</code> called <emphasis><?xxe-sn 2b06cb2u4g0 12?>specializations</emphasis>.
Each specialization has a guard that defines a <emphasis><?xxe-sn 2dc49lhpp1c 1?>condition</emphasis>
that has to be met in order to invoke this particular specialization. In
the example, specializations of <code><?xxe-sn 2b06cb2u4g0 13?>div</code>
have <code><?xxe-sn 2b06cb2u4g0 14?>iAmVeryFast</code> and <code><?xxe-sn 2b06cb2u4g0 15?>iAmVerySafe</code>
guards, respectively. Let's say that a code author writes two
specializations where the first one is a very fast division
implementation, while the second one is a very safe division
implementation since it checks division by zero, being "unacceptably slow"
due to an extra check instruction, though. This is a basis of <link
xlink:href="/d/concepts/polymorphism/"><?xxe-sn 2b3f3osfk74 2?>polymorphism</link>
— client's code <code><?xxe-sn 2b3f3osfk74 3?>test</code> is able to work
with any specialization, and the compiler must decide which one to invoke
with the only hint it has — annotation <code><?xxe-sn 2b3f3osfk74 5?>iAmVerySecure</code>
in the function <code><?xxe-sn 2b3f3osfk74 7?>test</code>'s
signature.</para>
<remark><?xxe-sn 2ccp2iy80zj 1td6aqezxvj7n?>"provides two specializations"
- возможно, лучший вариант "designates/assigns/allocates two
specializations". Или даже просто specifies/indicates. (PS заменил на
specifies)</remark>
<remark><?xxe-sn 2ccp2iy80zj 1td6aqezxvj7m?>"unbearably slow" - я бы
заменил на более нейтральное "too slow". Unbearable - это скорее об
ощущениях человека. Или, если под "unbearably" имеется в виду "недопустимо
медленный", тогда - unacceptably slow.</remark>
<note>
<?xxe-sn 2b3f3osfk74 n?>
<para><?xxe-sn 2b3f3osfk74 o?>All annotations (except <code><?xxe-sn 2b3f3osfk74 m?>entry</code>)
are custom defined by developer itself.</para>
</note>
<para><?xxe-sn 2b3f3osfk74 6?>This is when Transcend comes into play. By
adding a transcend rule as shown below it is possible to associate
annotation <code><?xxe-sn 2b3f3osfk74 8?>iAmVerySecure</code> with
invocation of specialization guarded by <code><?xxe-sn 2b3f3osfk74 9?>iAmVerySafe:</code></para>
<programlisting xml:id="Transcend_Example_1"><?xxe-sn 2b3f3osfk74 a?>name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15
dfa_callguard(SiteInv, iAmVerySafe):-
dfa_callfn(SiteInv, "div");
SiteInv = s(_, _, ScopeInv);
cfa_parent(ScopeInv, function(FnInv));
bind_func(FnInv, iAmVerySecure).</programlisting>
<para><?xxe-sn 2b3f3osfk74 b?>Transcend rules are written in ASP syntax —
common syntax to write logic programs. This particular rule reads that for
any function annotated with <code><?xxe-sn 2b3f3osfk74 c?>iAmVerySecure</code>,
certain specialization <code><?xxe-sn 2b3f3osfk74 d?>iAmVerySafe</code> is
chosen for <code><?xxe-sn 2b3f3osfk74 e?>div</code> invocation.</para>
<note>
<?xxe-sn 2b3f3osfk74 p?>
<para><?xxe-sn 2b3f3osfk74 q?>In this example an appropriate
specialization is statically resolved, so the other specialization isn't
even compiled.</para>
<remark><?xxe-sn 2ccp2iy80zj 1td6aqezxvj7o?>the, потому что их всего
две.</remark>
</note>
<para><?xxe-sn 2b3f3osfk74 f?>By providing custom rules it is possible to
implement any polymorphism strategy, be it performed statically or
dynamically. The example demonstrates basic workflow: Transcend gathers
available information about a program such as annotations and using custom
rules makes decisions to guide various aspects of compilation process,
particularly by selecting appropriate specializations as in the above
example.</para>
</section>
<section>
<?xxe-sn 2fchdmt7vgg 1?>
<title><?xxe-sn 2fchdmt7vgg 2?>More Advanced Example</title>
<para><?xxe-sn 2fchdmt7vgg 3?>Suppose we write a program to generate a web
page consisting of several blocks(e.g. a header, a footer) constructed
independently by different parts of our program. In order to organise the
code, we express our <emphasis><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8v?>intention</emphasis>
that all blocks should be sent to a client in a very specific order: first
a header, then a body and footer, as below:</para>
<programlisting xml:id="ExampleEov_1_Expectation"><?xxe-sn 2fchdmt7vgg 4?>name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15
eov_expect(
webpage, header, body; %we expect body to be sent after header
webpage, body, footer %.. and footer after body
).</programlisting>
<para><?xxe-sn 2fchdmt7vgg 5?>This is similar to <link
xlink:href="/d/exploitation/"><?xxe-sn 2fchdmt7vgg a?>Exploitation</link>:
we are working with the external resource <code><?xxe-sn 2fchdmt7vgg b?>webpage</code>
and want to take into account an exact order of resource exploiting
operations. Then, we write code like this:</para>
<programlisting><?xxe-sn 2fchdmt7vgg c?>send("Header"):: Content; eov_checkpoint(webpage, header).</programlisting>
<para><?xxe-sn 2fchdmt7vgg d?>We mark the operations we are interesting in
as <emphasis><?xxe-sn 2fchdmt7vgg e?>checkpoints</emphasis>(here
<code><?xxe-sn 2fds09lgw74 1?>header</code> is the name of a checkpoint
and <code><?xxe-sn 2fds09lgw74 3?>webpage</code> is the resource the
checkpoint refers to) and want to know are checkpoints executed in the
expected(as defined above) order.</para>
<para><?xxe-sn 2fchdmt7vgg f?>If it so happens that these blocks are
constructed in the correct order in our program we <emphasis><?xxe-sn 2fchdmt7vgg 6?>may</emphasis>
send them immediately. Otherwise, we must cache already constructed
content till a whole page is generated to ensure correctness. In other
words, clearly, there is an opportunity for optimizations for caching has
not only memory overhead but delays response latency(time before the first
block is sent) as well. We write two implementations <code><?xxe-sn 2fchdmt7vgg 7?>immediate_output</code>
and <code><?xxe-sn 2fchdmt7vgg 8?>cached_output</code> each for the
corresponding case:</para>
<programlisting xml:id="ExampleEov_1_Specializations"><?xxe-sn 2fchdmt7vgg 9?>name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15
//type to store either sending error code or cached content
Content = type variant {
- errcode:: int,
- message:: string
+ errcode(data::int),
+ message(data::string)
}.
//Send immediately:
guard:: immediate_output
{
send = function(content:: string):: Content
{
errcode(printf("%s", content))
}
}
//Cache content to send it later:
guard:: cached_output
{
send = function(content:: string):: Content
{
message(content)
}
}</programlisting>
<para><?xxe-sn 2fchdmt7vgg g?>These implementations should be registered
for the compiler to know which one to use:</para>
<programlisting xml:id="ExampleEov_1_Registration"><?xxe-sn 2fchdmt7vgg h?>name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15
eov_analysis(
success, immediate_output;
fail, cached_output
).</programlisting>
<para><?xxe-sn 2fchdmt7vgg i?>Predicate <code><?xxe-sn 2fchdmt7vgg j?>eov_analysis</code>
compares actual checkpoints execution order with the expected one and
chooses either of two implementations depending on the result. This way,
it is guarantied that immediate sending is chosen only if it is safe to do
so to avoid unnecessary caching.</para>
<para><?xxe-sn 2fchdmt7vgg k?>Thus we can safely change and adapt our
program knowing that clients always receive web page's content in the
correct order by automatically employing the most efficient content
delivery strategy depending on particular circumstances.</para>
</section>
<section>
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8u?>
<title><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8t?>Differences from other
languages</title>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8s?>it is convenient to talk about
<emphasis><?xxe-sn 2fs1xxghz93 -wunr7fl0rw88?>intentions</emphasis> in
order to outline a vast landscape of programming languages and point out
the place of Xreate on it, i.e. to compare languages depending on do they
allow to express a developer's intentions along with raw code that can be
used on many occasions, e.g. to validate the code's correctness.
Traditionally type system is used to declare intentions. At closer look,
types in (imperative) statically typed languages contain inseparable
combination of the following:</para>
<itemizedlist>
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8q?>
<listitem>
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8p?>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8o?>Intentions, such as "that
variable is a string".</para>
</listitem>
<listitem>
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8n?>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8m?>Usage patterns: a new code
should play nicely with the rest of a program, e.g. if a program works
with unicode, a new string variable should be also of unicode family
type(even if this is not necessary for a given part of code)</para>
</listitem>
<listitem>
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8l?>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8k?>Platform constraints, e.g.
if a platform supports wide strings natively, a new string variable
should also be a wide string.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8j?>In this regard, in general,
statically typed languages are <emphasis><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8i?>overconstrained</emphasis>,
they require developers to provide more information than they intend to.
This usually hinders code reuse and adaptation; to work on a new platform,
software requires porting: a process of re-expressing underlying
intentions once again with the new platform's constraints.</para>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8h?>On the other side, dynamically
typed languages are <emphasis><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8g?>underconstrained</emphasis>,
since they do not allow to express all desirable intentions. This leads to
disastrous inefficiency and code fragility because any errors can be
caught only at runtime.</para>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8f?>As an example, OOP languages are
hugely successful among other reasons because they provide
<emphasis><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8e?>classes</emphasis> to more
finely express intentions, e.g. <code><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8d?>String</code>,
<code><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8c?>UnicodeString</code>,
<code><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8b?>Utf8String</code> with exact
behaviour being hidden in implementation details.</para>
<para><?xxe-sn 2fs1xxghz93 -wunr7fl0rw8a?>Xreate in its turn is based on
the idea to allow developers express as much or as little intentions as
they want to. This is a way to reach one of the the language's goals to
facilitate writing of easily reusable and adaptable software. On a syntax
level, annotations are used to express intentions, e.g. <code><?xxe-sn 2fs1xxghz93 -wunr7fl0rw87?>string;i_dont_need(utf8)</code>(note
the modality, annotations can express boundaries, preferences, etc. ).
</para>
<para><?xxe-sn 2fxwo1r89a8 1?>This approach obviously leads to problems
with software's performance and efficiency. For most high level languages,
compilers rely on defaults to fill in unspecified by the developer gaps in
the exact implementation details. Usually languages provide standard,
default data structures the developer have no control over. However Xreate
follows another approach: to resolve this contradiction, the compiler
determines necessary implementation details not only depending on
annotations, but also by looking at usage patterns along with platform
properties trying to infer most efficient implementations in any given
circumstances.</para>
</section>
</chapter>
diff --git a/grammar/xreate.ATG b/grammar/xreate.ATG
index 84ac92c..42ffdbd 100644
--- a/grammar/xreate.ATG
+++ b/grammar/xreate.ATG
@@ -1,707 +1,828 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.h"
#include <string>
#include <stack>
+#include <sstream>
#define wprintf(format, ...) \
char __buffer[100]; \
wcstombs(__buffer, format, 100); \
fprintf(stderr, __buffer, __VA_ARGS__)
using namespace std;
COMPILER Xreate
- details::inconsistent::AST* root = nullptr; // current program unit
+details::inconsistent::AST* root = nullptr; // current program unit
- void ensureInitalizedAST(){
- if (root == nullptr) root = new details::inconsistent::AST();
- }
+void SemErr(std::initializer_list<std::wstring> msgs){
+ std::wstringstream output;
+ for(const auto& msg: msgs){output << msg;}
+ SemErr(output.str().c_str());
+}
+
+void ensureInitalizedAST(){
+ if (root == nullptr) root = new details::inconsistent::AST();
+}
struct {
std::stack<CodeScope*> scopesOld;
CodeScope* scope = nullptr;
} context;
void pushContextScope(CodeScope* scope){
context.scopesOld.push(context.scope);
context.scope = scope;
}
void popContextScope(){
context.scope = context.scopesOld.top();
context.scopesOld.pop();
}
int nextToken()
{
scanner->ResetPeek();
return scanner->Peek()->kind;
}
bool checkTokenAfterIdent(int key){
if (la->kind != _ident) return false;
return nextToken() == key;
}
bool checkParametersList()
{
return la->kind == _ident && nextToken() == _lparen;
}
bool checkInfix()
{
return la->kind == _ident && nextToken() == _ident;
}
bool checkIndex()
{
return la->kind == _ident && nextToken() == _lbrack;
}
+bool checkListIndex()
+{
+ return la->kind == _lcurbrack && nextToken() == _lbrack;
+}
+
bool checkFuncDecl()
{
if (la->kind != _ident) return false;
int token2 = nextToken();
int token3 = scanner->Peek()->kind;
- return token2 == _assign && (token3 == _function || token3 == _pre);
+ return token2 == _assign && token3 == _function;
}
bool checkAssignment()
{
if (la->kind != _ident) return false;
scanner->ResetPeek();
int token2 = scanner->Peek()->kind;
if (token2 == _lcurbrack) {
scanner->Peek();
int token3 = scanner->Peek()->kind;
if (token3 != _rcurbrack) return false;
int token4 = scanner->Peek()->kind;
return token4 == _assign;
}
return token2 == _assign;
}
-void recognizeIdentifier(Expression& i){
- if (!context.scope->recognizeIdentifier(i)){
- root->postponeIdentifier(context.scope, i);
- }
+void recognizeIdentifier(Expression& id, const std::wstring& hint){
+ if (!context.scope)
+ SemErr({L"Identifier found in undefined scope: ", hint});
+
+ if (!context.scope->recognizeIdentifier(id)){
+ root->postponeIdentifier(context.scope, id);
+ }
}
enum SwitchKind{SWITCH_NORMAL, SWITCH_META};
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
ident = (letter ['-' letter] | '_') {letter ['-' letter] | digit | '_' }.
number = digit{digit}.
string = '"' { any } '"'.
function = "function".
- pre = "pre".
comma = ','.
period = '.'.
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
lcurbrack = '{'.
rcurbrack = '}'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
- context = "context".
tagcolon = "::".
lse = "<=".
lss = "<".
gte = ">=".
gtr = ">".
ne1 = "!=".
ne2= "<>".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
Xreate = (. Function* function; ensureInitalizedAST(); .)
{( //RuleDecl
InterfaceData | Imprt | GuardSection
| IF(checkFuncDecl()) FDecl<function> (. root->add(function); .)
| TDecl
| SkipModulesSection
)} (. .)
.
-Ident<std::wstring& name>
-= ident (. name = t->val; .).
+Ident<std::wstring& name>=
+ ident (. name = t->val; .).
+
+// recognition
+IdentR<Expression &e> = (. std::wstring name; .)
+ Ident<name> (. e = Expression(Atom<Identifier_t>(name)); .)
+ (. recognizeIdentifier(e, name); .).
+
+//versioning
+IdentV<Expression& e>= (. std::wstring name; .)
+ Ident<name> (. e = Expression(Atom<Identifier_t>(name)); .)
+ [ Version<e> ].
-VarIdent<Expression& e>
-= ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
- [ lcurbrack (
- ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .)
- | number (. Attachments::put<versions::VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
- ) rcurbrack ]
+//recognition + versioning
+IdentVR<Expression& e>= (. std::wstring name; .)
+ Ident<name> (. e = Expression(Atom<Identifier_t>(name)); .)
+ [ Version<e> ] (. recognizeIdentifier(e, name); .)
.
+
+Version<Expression &e>=
+ lcurbrack (
+ ident (. SemErr({L"var version as ident is not implemented yet"}); .)
+ | number (. Attachments::put<versions::VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
+ ) rcurbrack .
-FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .)
+FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; Expression binding; .)
Ident<fname> assign
-[pre (. flagIsPrefunct = true; .)]
-function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .)
+function (. f = new Function(fname); CodeScope* entry = f->getEntryScope(); .)
-[lparen Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
+[lparen Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
{comma Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom <Identifier_t>(argName), move(binding));.)
} rparen]
-[ tagcolon
-( IF(flagIsPrefunct) FnTag<f>
- | Type<typOut>
-)
-{';' FnTag<f> }]
+[ tagcolon Type<typOut> {';' FnTag<f> }]
BDecl<entry> (. const_cast<Expression&>(entry->getBody()).bindType(move(typOut));.)
.
-GuardSection<>= (. Expression guard; Function* f; .)
- "guard" tagcolon MetaSimpExpr<guard>
- lcurbrack { FDecl<f> (. f->guard = guard; root->add(f); .)
- } rcurbrack.
+GuardSection<>= (. std::wstring arg, guardI; Expression guardE, guardBinding; Function* f; TypeAnnotation guardT; .)
+ "guard" lparen
+ [Ident<arg>] tagcolon Ident<guardI> (. guardE = Expression(Operator::CALL, {Atom<Identifier_t>(guardI)}); bool res = root->recognizeVariantConstructor(guardE); .)
+ (. if(!res) SemErr(coco_string_create("Can't recognize a guard"));.)
+ (. if (!arg.empty()) guardE.addBindings({Atom<Identifier_t>(arg)}); .)
+ (. guardBinding.type = TypeAnnotation(TypeOperator::GUARD, {guardE.type}); guardBinding.type.__valueCustom = Atom<Identifier_t>(guardI).get(); .)
+ rparen lcurbrack {
+ FDecl<f> (. f->guard = guardE; if (!arg.empty()){f->addBinding(Atom<Identifier_t>(arg), Expression(guardBinding));} .)
+ (. root->add(f); .)
+ } rcurbrack
+.
/**
* TYPES
*
*/
TypeTerm<TypePrimitive& typ> = (. std::wstring tid; .)
- ("string" (. typ = TypePrimitive::String;.)
- | "num" (. typ = TypePrimitive::Num;.)
- | "int" (. typ = TypePrimitive::Int;.)
- | "float" (. typ = TypePrimitive::Float;.)
- | "bool" (. typ = TypePrimitive::Bool; .)
- | "i8" (. typ = TypePrimitive::I8; .)
- | "i32" (. typ = TypePrimitive::I32; .)
- | "i64" (. typ = TypePrimitive::I64; .)
+ ( "string" (. typ = TypePrimitive::String;.)
+ | "int" (. typ = TypePrimitive::Int;.)
+ | "float" (. typ = TypePrimitive::Float;.)
+ | "bool" (. typ = TypePrimitive::Bool; .)
+ | "i8" (. typ = TypePrimitive::I8; .)
+ | "i32" (. typ = TypePrimitive::I32; .)
+ | "i64" (. typ = TypePrimitive::I64; .)
).
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid; std::string field; .)
(
TList<typ>
| TRecord<typ>
| TVariant<typ>
+| TPred<typ>
| TSlave<typ>
+| TRef<typ>
| TypeTerm<typ3> (. typ = typ3; .)
| IF (checkIndex()) Ident<tid> lbrack
TypeIndex<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(field); .)
{comma TypeIndex<field> (. typ.fields.push_back(field); .)
} rbrack
-| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
- [lparen Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
- {comma Type<typ2> (. typ.__operands.push_back(typ2); .)
+| Ident<tid> (. typ = TypeAnnotation(TypeOperator::ALIAS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
+ [lparen Type<typ2> (. typ.__operands.push_back(typ2); .)
+ {comma Type<typ2> (. typ.__operands.push_back(typ2); .)
} rparen]
| '*' (.typ = TypeAnnotation(); .)
) .
TypeIndex<std::string& name> =
(
number (. name = Atom<Identifier_t>(t->val).get(); .)
| string (. name = Atom<String_t>(t->val).get(); .)
)
.
TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
- lbrack Type<ty> rbrack (. typ = TypeAnnotation(TypeOperator::LIST_ARRAY, {ty}); .)
+ lbrack Type<ty> rbrack (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .)
.
-TRecord<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring key; size_t keyCounter=0; .)
- lcurbrack
- (
- IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
- | Type<t> (. key = to_wstring(keyCounter++); .)
-
- ) (. typ = TypeAnnotation(TypeOperator::LIST_RECORD, {t}); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
- {comma (
- IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
- | Type<t> (. key = to_wstring(keyCounter++); .)
-
- ) (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
- } rcurbrack.
+TRecordBody<TypeAnnotation& typ> =
+ (. TypeAnnotation t; std::wstring key; size_t keyCounter=0;
+ typ = TypeAnnotation(TypeOperator::RECORD, {});
+ .)
+{
+ (
+ IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon
+ | (. key = to_wstring(keyCounter++); .)
+ )
+ Type<t> [comma] (. typ.__operands.push_back(t); .)
+ (. typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
+}.
+
+TRecord<TypeAnnotation& typ> =
+ lcurbrack TRecordBody<typ> rcurbrack
+ (. if(!typ.__operands.size()) SemErr(coco_string_create("Record type can't be empty.")); .)
+.
+
+TVariantRec<TypeAnnotation& typ> = (. TypeAnnotation typVoid; .)
+ lparen TRecordBody<typ> rparen
+ (. if(typ.__operands.size()==0) typ = typVoid; .)
+.
-TVariant<TypeAnnotation& typ>= (. TypeAnnotation t, typVoid; std::vector<TypeAnnotation> operands; std::vector<Atom<Identifier_t>> keys; std::wstring variant; .)
- "variant" lcurbrack
- Ident<variant> (. t=typVoid; .)
- [tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
-
- {comma Ident<variant> (. t=typVoid; .)
- [tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
- }
- rcurbrack (. typ = TypeAnnotation(TypeOperator::VARIANT, {}); typ.__operands = operands; typ.addFields(std::move(keys)); .)
-.
-
-TSlave<TypeAnnotation& typ>= (. std::wstring identMaster; .)
- "slave" Ident<identMaster> (. typ = TypeAnnotation(TypeOperator::SLAVE, {}); typ.__valueCustom = Atom<Identifier_t>(identMaster).get(); .)
+TVariantBody<TypeAnnotation& typ> = (. TypeAnnotation t, typVoid; std::vector<TypeAnnotation> operands; std::vector<Atom<Identifier_t>> keys; std::wstring v; .)
+lcurbrack
+ { (. t = typVoid; .)
+ Ident<v> [TVariantRec<t>] (. keys.push_back(Atom<Identifier_t>(v)); operands.push_back(t); .)
+ [comma]
+ }
+rcurbrack
+ (. typ = TypeAnnotation(TypeOperator::VARIANT, {});
+ typ.__operands = operands;
+ typ.addFields(std::move(keys));
+ .)
+.
+
+TVariant<TypeAnnotation& typ>=
+ "variant" TVariantBody<typ>
+ (. if(!typ.__operands.size()) SemErr(coco_string_create("Variant type can't be empty.")); .)
+.
+
+TPred<TypeAnnotation& typ>=
+ "predicate" TVariantBody<typ>
+ (. if(!typ.__operands.size()) SemErr(coco_string_create("Predicate type can't be empty.")); .)
+.
+
+TSlave<TypeAnnotation& typ>=
+ "slave" (. typ = TypeAnnotation(TypeOperator::SLAVE, {}); .)
+ lparen
+ string (. typ.__valueCustom = Atom<String_t>(t->val).get(); .)
+ rparen
+.
+
+TRef<TypeAnnotation& typ>= (. TypeAnnotation typChild; .)
+ "ref" lparen Type<typChild> rparen (. typ = TypeAnnotation(TypeOperator::REF, {typChild}); .)
.
TDecl = (. TypeAnnotation t; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
Ident<tname> assign "type"
[lparen Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
- {comma Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
+ {comma Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
} rparen]
- Type<t>period (. t.addBindings(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
+ Type<t>[period] (. t.addBindings(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
.
ContextDecl<CodeScope * scope> = (. Expression tag; .)
-context tagcolon
+"context" tagcolon
MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
-VDecl<CodeScope* f> = (. std::wstring vname; Expression var, value;.)
- VarIdent<var> assign ExprTyped<value> (. Symbol identSymbol = f->addDefinition(move(var), move(value));
- Attachments::put<SymbolAlias>(value, identSymbol);
+VDecl<CodeScope* f> = (. Expression var, value;.)
+ IdentV<var> assign ExprTyped<value> (. Symbol identSymbol = f->addDefinition(move(var), move(value));
+ Attachments::put<ExprAlias_A>(value, identSymbol);
.)
.
-BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); .)
+BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); bool flagBodyFound = false; .)
{(IF(checkAssignment()) VDecl<scope> period
// | RuleContextDecl<scope>
| ContextDecl<scope>period
- | ExprTyped<body> (. scope->setBody(body); Attachments::put<SymbolAlias>(body, Symbol{ScopedSymbol::RetSymbol, scope});.)
+ | ExprTyped<body> (. scope->setBody(body); flagBodyFound = true; Attachments::put<ExprAlias_A>(body, Symbol{ScopedSymbol::RetSymbol, scope});.)
)}
- rcurbrack (. popContextScope(); .)
+ rcurbrack (. if(!flagBodyFound) SemErr(coco_string_create("Code block with an empty body!"));
+ popContextScope();
+ .)
.
IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root->add(new CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new CodeScope(context.scope)); .)
"if" lparen Expr<cond> rparen (. e = Expression(Operator::IF, {cond}); .)
tagcolon ExprAnnotations<e>
BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e> =
(.
Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl;
ManagedScpPtr block = root->add(new CodeScope(context.scope));
.)
"loop"
(
"map" lparen Expr<eIn> implic Ident<varEl>
(. e = Expression(Operator::MAP, {eIn}); .)
tagcolon ExprAnnotations<tagsEl> rparen tagcolon ExprAnnotations<e>
(.
e.addBindings({Atom<Identifier_t>(varEl)});
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
.)
BDecl<&*block>
(. e.addBlock(block); .)
| "fold" lparen Expr<eIn> implic Ident<varEl> tagcolon ExprAnnotations<tagsEl>
['|' Expr<eFilters> ] comma Expr<eAcc> implic Ident<varAcc>rparen
(.
e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
.)
tagcolon ExprAnnotations<e>
- (.
+ (.
+ Expression varAccBindingE; varAccBindingE.type = e.type;
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
- block->addBinding(Atom<Identifier_t>(varAcc), Expression());
+ block->addBinding(Atom<Identifier_t>(varAcc), move(varAccBindingE));
.)
BDecl<&*block>
(. e.addBlock(block); .)
| lparen Expr<eAcc> implic Ident<varAcc> rparen
(.
- e = Expression(Operator::INF, {eAcc});
+ e = Expression(Operator::FOLD_INF, {eAcc});
e.addBindings({Atom<Identifier_t>(varAcc)});
- block->addBinding(Atom<Identifier_t>(varAcc), Expression());
.)
- tagcolon ExprAnnotations<e> BDecl<&*block>
+ tagcolon ExprAnnotations<e>
+ (.
+ Expression varAccBindingE; varAccBindingE.type = e.type;
+ block->addBinding(Atom<Identifier_t>(varAcc), move(varAccBindingE));
+ .)
+ BDecl<&*block>
(. e.addBlock(block); .)
).
// Switches
SwitchDecl<Expression& eSwitch, SwitchKind flagSwitchKind> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.)
"switch"
(
SwitchVariantDecl<eSwitch>
| SwitchLateDecl<eSwitch>
| lparen ExprTyped<eCondition> rparen tagcolon ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
)
.
CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); Expression condition; .)
"case"
( IF(flagSwitchKind == SWITCH_META)
lparen MetaSimpExpr<condition> rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.)
| "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
exprCase.addBlock(scope);
outer.operands.insert(++outer.operands.begin(), exprCase); .)
| lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .)
).
CaseParams<CodeScope* scope> = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
{comma ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
} (. scope->setBody(guard); popContextScope(); .)
.
SwitchLateDecl<Expression& expr> =
(.
std::wstring aliasCondition; Expression exprCondition, aliasAnns;
expr = Expression(Operator::SWITCH_LATE, {});
ManagedScpPtr scope = root->add(new CodeScope(context.scope));
.)
"late" lparen Expr<exprCondition> [implic Ident<aliasCondition>] [tagcolon ExprAnnotations<aliasAnns>] rparen
tagcolon ExprAnnotations<expr> BDecl<&*scope>
(.
expr.addArg(Expression(exprCondition));
expr.addBlock(scope);
std::string alias;
if(aliasCondition.empty()){
if(exprCondition.__state != Expression::IDENT){
SemErr(coco_string_create("An identifier expected in the short form"));
return;
}
//Use exprCondition as identifier
alias = exprCondition.getValueString();
} else {
//Use aliasCondition
alias = Atom<Identifier_t>(move(aliasCondition)).get();
}
expr.addBindings({Atom<Identifier_t>(string(alias))});
scope->addBinding(Atom<Identifier_t>(move(alias)), move(aliasAnns));
.)
.
SwitchVariantDecl<Expression& expr> =
(. Expression varTested; std::wstring varAlias; bool flagAliasFound = false; expr = Expression(Operator::SWITCH_VARIANT, {}); .)
"variant" lparen Expr<varTested> [implic Ident<varAlias>
(. flagAliasFound = true; .)
] [tagcolon ExprAnnotations<varTested>] rparen tagcolon ExprAnnotations<expr>
(. expr.addArg(std::move(varTested));
if (flagAliasFound) {
expr.addBindings({Atom<Identifier_t>(varAlias)});
} else {
if(varTested.__state == Expression::IDENT){
expr.addBindings({Atom<Identifier_t>(string(varTested.getValueString()))});
}
}
.)
CaseVariantDecl<expr> {CaseVariantDecl<expr>}
.
CaseVariantDecl<Expression& expr> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); std::wstring key; scope->addBinding(Atom<Identifier_t>(string(expr.bindings.front())), Expression()); .)
"case" lparen Ident<key> rparen (. expr.addArg(root->recognizeVariantConstructor(Atom<Identifier_t>(std::move(key)))); .)
BDecl<&*scope> (. expr.addBlock(scope); .)
.
IntrinsicDecl<Expression& outer>= (. std::wstring name; .)
"intrinsic"
(
- Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom<Identifier_t>(name)); .)
- lparen [CalleeParams<outer>] rparen
+ Ident< name>
+ (. outer = Expression(Operator::CALL_INTRINSIC, {});
+ outer.setValue(Atom<Identifier_t>(name));
+ root->recognizeIntrinsic(outer);
+ .)
+ lparen [CalleeParams<outer>] rparen
| "query" (. outer = Expression(Operator::QUERY, {}); .)
(
"late" IntrinsicQueryLateDecl<outer>
| lparen [CalleeParams<outer>] rparen
)
).
IntrinsicQueryLateDecl<Expression& expr> =
(.
std::wstring predicateAlias; Expression predicateE, predicateAnns;
expr = Expression(Operator::QUERY_LATE, {});
ManagedScpPtr scope = root->add(new CodeScope(context.scope));
.)
lparen Expr<predicateE> implic Ident<predicateAlias> tagcolon ExprAnnotations<predicateAnns> rparen
tagcolon ExprAnnotations<expr> BDecl<&*scope>
(.
expr.addArg(move(predicateE));
expr.addBindings({Atom<Identifier_t>(wstring(predicateAlias))});
scope->addBinding(Atom<Identifier_t>(move(predicateAlias)), move(predicateAnns));
expr.addBlock(scope);
.)
.
SequenceDecl<Expression& sequence> = (. sequence = Expression(); sequence.setOp(Operator::SEQUENCE); ManagedScpPtr scope = root->add(new CodeScope(context.scope)); .)
"seq" BDecl<&*scope> (. sequence.blocks.push_back(&*scope); scope = root->add(new CodeScope(&*scope)); .)
{ (. scope = root->add(new CodeScope(&*scope)); .)
BDecl<&*scope> (. sequence.blocks.push_back(&*scope); .)
}.
/*============================ INTERFACES ===============================*/
Imprt<> =
"import" "raw" lparen string (. root->__rawImports.push_back(Atom<String_t>(t->val).get()); .)
rparen period.
InterfaceData<> = "interface" lparen
( "dfa" rparen InterfaceDFA
- | "extern-c" rparen InterfaceExternC
+// | "extern-c" rparen InterfaceExternC
| "cfa" rparen InterfaceCFA
).
-InterfaceExternC<> = (. ExternData data; .)
- lcurbrack {IncludeExternDecl<data> | LibExternDecl<data> } rcurbrack
- (. root->addExternData(move(data)); .)
-.
-
-LibExternDecl<ExternData& data> = (. std::wstring pkgname, libname; .)
- Ident<libname> assign "library" tagcolon "pkgconfig"
- lparen string (. pkgname = t->val; .)
- rparen period (. data.addLibrary(Atom<Identifier_t>(libname), Atom<String_t>(pkgname)); .)
-.
-
-IncludeExternDecl<ExternData& data> = (. Expression inc; .)
- "include" ListLiteral<inc> period (. data.addIncludeDecl(move(inc)); .)
-.
+// InterfaceExternC<> = (. ExternData data; .)
+// lcurbrack {ExternHeadersDecl<data> | ExternAliasDecl<data> } rcurbrack
+// (. root->addExternData(move(data)); .)
+// .
+//
+// ExternPkgDecl<std::wstring& package> =
+// "pkgconfig" lparen
+// string (. package = t->val.)
+// rparen
+// .
+//
+// ExternAliasDecl<ExternData& data> = (. std::wstring alias, package; .)
+// Ident<alias> assign "library" lparen ExternPkgDecl<package> rparen period
+// (. data.addLibAlias(Atom<Identifier_t>(alias), Atom<String_t>(package)); .)
+// .
+//
+// ExternHeadersDecl<ExternData& data> = (. std::list<std::string> listInc; std::wstring& package; .)
+// "include"
+// [lparen
+// (
+// Ident<alias> (. data.requireLibAlias(Atom<Identifier_t>(alias)); .)
+// | ExternPkgDecl<package> (. data.requireLibPackage(Atom<String_t>(package)); .)
+// )
+// rparen]
+// lcurbrack { string (. listInc.push_back(Atom<String_t>(t->val).get()); .)
+// [comma] } rcurbrack [period] (. data.requireHeaders(listInc); .)
+// .
InterfaceDFA<> = lcurbrack { InstructDecl } rcurbrack .
InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
"operator" InstructAlias<op> tagcolon lparen (.scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
comma MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] rparen [ implic MetaSimpExpr<tag> (. tags[0] = tag; .)
] (. root->addDFAData(move(scheme)); .)
period.
InstructAlias<Operator& op> =
(
"map" (. op = Operator::MAP; .)
| "list_range" (. op = Operator::LIST_RANGE; .)
| "list" (. op = Operator::LIST; .)
| "fold" (. op = Operator::FOLD; .)
| "index" (. op = Operator::INDEX; .)
).
InterfaceCFA<> = lcurbrack { InstructCFADecl } rcurbrack .
InstructCFADecl<> = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands; .)
"operator" InstructAlias<op> tagcolon (. scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
comma MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] period (. root->addInterfaceData(CFA, move(scheme)); .).
/*============================ METAPROGRAMMING ===============================*/
// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
// }.
FnTag<Function* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
MetaSimpExpr<tag>
['-' TagMod<mod>] (. f->addTag(std::move(tag), mod); .).
TagMod<TagModifier& mod> =
( "assert" (. mod = TagModifier::ASSERT; .)
| "require" (. mod = TagModifier::REQUIRE; .)
).
// RuleDecl<> =
// "rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
// lparen Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
// {comma Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
// } rparen
// ["case" RGuard<guards> {comma RGuard<guards>}]
// lcurbrack RBody<args, guards> rcurbrack .
/* - TODO use RGuard for guards-*/
// RuleContextDecl<CodeScope* scope> = (.Expression eHead, eGuards, eBody; .)
// "rule" "context" tagcolon MetaSimpExpr<eHead>
// "case" lparen MetaSimpExpr<eGuards> rparen
// lcurbrack MetaSimpExpr<eBody> rcurbrack (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .).
// Domain<DomainAnnotation& dom> =
// (
// "function" (. dom = DomainAnnotation::FUNCTION; .)
// | "variable" (. dom = DomainAnnotation::VARIABLE; .)
// ).
// RGuard<RuleGuards& guards>= (. Expression e; .)
// MetaExpr<e> (. guards.add(std::move(e)); .).
// MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
// MetaExpr2<e>
// [MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
// ].
// MetaExpr2<Expression& e>=
// (
// lparen MetaExpr<e> rparen
// | MetaSimpExpr<e>
// ).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
-( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
-| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
-lparen [ MetaCalleeParams<e> ] rparen
-| IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
- (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
- e.addArg(Expression(Atom<Identifier_t>(i1)));
- e.addArg(std::move(e2));
- .)
-| Ident<i1> (. e = Expression(Operator::CALL, {Atom<Identifier_t>(i1)}); .)
-).
+ (
+ '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
+ | IF(checkParametersList()) Ident<i1>
+ (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))});
+ if (!root->recognizeVariantConstructor(e))
+ SemErr({L"Undefined predicate: ", i1});
+ .)
+ lparen [ MetaCalleeParams<e> ] rparen
+ | IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
+ (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
+ e.addArg(Expression(Atom<Identifier_t>(i1)));
+ e.addArg(std::move(e2));
+ .)
+ | IdentR<e>
+ | number (. e = Expression(Atom<Number_t>(t->val)); .)
+ ).
MetaCalleeParams<Expression& e> = (. Expression e2; .)
MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
{comma MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
}.
// RBody<const RuleArguments& args, const RuleGuards& guards> =
// (. Expression e; std::wstring msg; .)
// "warning" MetaExpr<e> ["message" string (. msg = t->val; .)
// ] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
// .
// MetaOp< Operator& op> =
// implic (. op = Operator::IMPL; .)
// .
/*============================ Expressions ===============================*/
ExprAnnotations<Expression& e> = (. TypeAnnotation typ; std::list<Expression> tags; Expression tag; e.tags.clear();.)
Type<typ> (. e.bindType(move(typ)); .)
{';' MetaSimpExpr<tag> (. tags.push_back(tag); .)
} (. e.addTags(tags); .)
.
ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
-Expr< Expression& e> (. Operator op; Expression e2; .)
+Expr< Expression& e> (. Expression e2; .)
+= ExprLogicAnd<e>
+ [ ('or' | 'OR') Expr<e2> (. e = Expression(Operator::OR, {e, e2}); .)
+ ]
+.
+
+ExprLogicAnd< Expression& e> (. Expression e2; .)
+= ExprRel<e>
+ [ ('and' | 'AND') ExprLogicAnd <e2> (. e = Expression(Operator::AND, {e, e2}); .)
+ ]
+.
+
+ExprRel< Expression& e> (. Operator op; Expression e2; .)
= ExprArithmAdd<e>
- [ RelOp<op>
- ExprArithmAdd<e2> (. e = Expression(op, {e, e2}); .)
- ].
+ [ RelOp<op> ExprRel<e2> (. e = Expression(op, {e, e2}); .)
+ ]
+.
ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .)
ExprArithmMul< e>
- [ AddOp< op>
- ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
+ [
+ AddOp<op>ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
].
ExprArithmMul< Expression& e> (. Operator op; Expression e2; .)
-= ExprPostfix< e>
+= ExprUpdate<e>
[ MulOp< op>
ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .)
].
+
+ExprUpdate<Expression& e>= (. Expression e2; .)
+ ExprPostfix< e>
+ [
+ colon
+ ( IF(checkListIndex()) ListIndexLiteral<e2>
+ | ListLiteral<e2>) (. e = Expression(Operator::UPDATE, {e, e2}); .)
+ ].
+
ExprPostfix<Expression& e>
= Term<e>
[ (. e = Expression(Operator::INDEX, {e}); .)
{lbrack CalleeParams<e> rbrack }
].
Term< Expression& e> (. std::wstring name; e = Expression(); .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); root->recognizeVariantConstructor(e); .)
lparen [CalleeParams<e>] rparen
- | VarIdent<e> (. recognizeIdentifier(e); .)
- | ListLiteral<e>
+ | IdentVR<e>
+ | ListLiteral<e>
| ListRangeLiteral<e>
| LoopDecl<e>
| IfDecl<e>
| SwitchDecl<e, SWITCH_NORMAL>
| IntrinsicDecl<e>
| SequenceDecl<e>
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
| "true" (. e = Expression(Atom<Number_t>(1)); e.bindType(TypePrimitive::Bool); .)
| "false" (. e = Expression(Atom<Number_t>(0)); e.bindType(TypePrimitive::Bool); .)
| "undef" (. e = Expression(Operator::UNDEF, {}); .)
| '-' Term<e> (. e = Expression(Operator::NEG, {e}); .)
| lparen ExprTyped<e> rparen
).
-ListLiteral<Expression& e> = (. std::wstring key; Expression val; std::list<Atom<Identifier_t>> keys; size_t keyCounter=0; .)
+ListLiteral<Expression& e> = (. std::wstring key;
+ Expression val;
+ std::list<Atom<Identifier_t>> keys;
+ e = Expression(Operator::LIST, {});
+ .)
+ lcurbrack {
+ ( IF(checkTokenAfterIdent(_assign)) Ident<key> assign
+ | (. key = L""; .)
+ ) Expr<val> (. keys.push_back(Atom<Identifier_t>(key));
+ e.operands.push_back(val);
+ .)
+ [comma] } rcurbrack (. e.addBindings(keys.begin(), keys.end()); .)
+.
+
+ListIndexLiteral<Expression& e> = (. e = Expression(Operator::LIST_INDEX, {});Expression valE;.)
lcurbrack
- (IF(checkTokenAfterIdent(_assign)) Ident<key> assign Expr<val>
- | Expr<val> (. key = to_wstring(keyCounter++); .)
- ) (. keys.push_back(Atom<Identifier_t>(key)); e = Expression(Operator::LIST, {val}); .)
- {comma (IF(checkTokenAfterIdent(_assign)) Ident<key> assign Expr<val>
- | Expr<val> (. key = to_wstring(keyCounter++); .)
- ) (. e.addArg(Expression(val)); keys.push_back(Atom<Identifier_t>(key)); .)
- } rcurbrack (. e.addBindings(keys.begin(), keys.end()); .)
- .
+ { (. Expression idxE(Operator::LIST, {});.)
+ lbrack CalleeParams<idxE> rbrack
+ assign Expr<valE>[comma] (. e.operands.push_back(idxE); e.operands.push_back(valE); .)
+ }
+ rcurbrack
+.
ListRangeLiteral<Expression& e> = (. Expression eFrom, eTo; .)
lbrack Expr<eFrom> ".." Expr<eTo> rbrack (. e = Expression(Operator::LIST_RANGE, {eFrom, eTo}); .)
.
CalleeParams<Expression& e> = (. Expression e2; .)
ExprTyped<e2> (. e.addArg(Expression(e2)); .)
{comma ExprTyped<e2> (. e.addArg(Expression(e2)); .)
}.
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| (ne1 | ne2) (. op = Operator::NE; .)
| lse (. op = Operator::LSE; .)
| lss (. op = Operator::LSS; .)
| gte (. op = Operator::GTE; .)
| gtr (. op = Operator::GTR; .)
).
SkipModulesSection = "module" {ANY} (lcurbrack {ANY} rcurbrack | '.').
END Xreate.
diff --git a/scripts/containers/RecUpdateInLoop1.xreate b/scripts/containers/RecUpdateInLoop1.xreate
new file mode 100644
index 0000000..18f677e
--- /dev/null
+++ b/scripts/containers/RecUpdateInLoop1.xreate
@@ -0,0 +1,12 @@
+Rec = type {x:: int, y:: int}.
+
+test = function(base:: int):: int; entry() {
+ fields = intrinsic rec_fields("Rec"):: [string]; i12n(on()).
+
+ result = loop fold(fields->field:: string, {undef, 0}->ctx):: {rec:: Rec, id:: int}
+ {
+ { (ctx["rec"]::Rec) : {[field] = base + ctx["id"] }, ctx["id"]+1 }:: {rec:: Rec, id:: int}
+ }.
+
+ result["rec"]["y"]
+}
diff --git a/scripts/containers/minmax.xreate b/scripts/containers/minmax.xreate
new file mode 100644
index 0000000..9b9b8c6
--- /dev/null
+++ b/scripts/containers/minmax.xreate
@@ -0,0 +1,241 @@
+El = type {idx:: int, val:: int}.
+PairT = type(X) {X, X}.
+
+Pair = type PairT(int).
+PairEl = type PairT(El).
+
+min = function(x:: int, y:: int):: int
+{
+ if (x < y):: int { x } else { y }
+}
+
+max = function(x:: int, y:: int):: int
+{
+ if (x > y):: int { x } else { y }
+}
+
+minEl = function(e1:: El, e2:: El):: El
+{
+ if (e1["val"] < e2["val"]):: El {e1} else {e2}
+}
+
+maxEl = function(e1:: El, e2:: El):: El
+{
+ if (e1["val"] > e2["val"]):: El {e1} else {e2}
+}
+
+minElIdx = function(x:: El, y:: El):: El
+{
+ if (x["idx"] < y["idx"]):: El {x} else {y}
+}
+
+maxElIdx = function(x:: El, y:: El):: El
+{
+ if (x["idx"] > y["idx"]):: El {x} else {y}
+}
+
+minLstEl = function(x:: El, y:: El):: El
+{
+ if (x["val"] <= y["val"]):: El {x} else {y}
+}
+
+maxLstEl = function(x:: El, y:: El):: El
+{
+ if (x["val"] >= y["val"]):: El {x} else {y}
+}
+
+fn-minmax1 = function:: {min:: int, max:: int}
+{
+ arr = {25, 37, 12, 6, 5, 19, 3, 20}:: [int].
+
+ loop fold(arr->el:: int, {1000, 0}->state):: {min:: int, max:: int}
+ {
+ {
+ min(el, state["min"]),
+ max(el, state["max"])
+ }:: {min:: int, max:: int}
+ }
+}
+
+fn-minmax2 = function:: int
+{
+ arr = {
+ {1, 72}, {3, 8}, {2, 5}, {3, 4}, {11, 1}, {6, 5}, {9, 2}
+ } :: [{int, int}].
+
+ loop fold(arr->rect:: {int, int}, 1000->squareMin):: int
+ {
+ square = rect[0] * rect[1]:: int.
+
+ min(square, squareMin)
+ }
+}
+
+fn-minmax3 = function:: int
+{
+ arr = {
+ {1, 72}, {3, 8}, {2, 5}, {3, 4}, {11, 1}, {6, 5}, {9, 2}
+ } :: [{int, int}].
+
+ loop fold(arr->rect:: {int, int}, 0->perMax):: int
+ {
+ per = 2 * (rect[0] + rect[1]):: int.
+ max(per, perMax)
+ }
+}
+
+fn-minmax4 = function:: int
+{
+ arr = {25, 37, 12, 6, 5, 19, 3, 20}:: [int].
+ minInit = {0, 25}:: El.
+ result = loop fold(arr->el:: int, {0, minInit}->state):: {idx:: int, minEl:: El}
+ {
+ elCur = {state["idx"], el}:: El.
+ idxNext = state["idx"] + 1:: int.
+
+ {idxNext, minEl(elCur, state["minEl"])}:: {idx:: int, minEl:: El}
+ }.
+
+ result["minEl", "idx"]
+}
+
+fn-minmax5 = function:: El
+{
+ input = {
+ {1, 72}, {3, 8}, {2, 5}, {3, 4}, {11, 1}, {6, 5}, {9, 2}
+ } :: [{int, int}].
+
+ resultInit = {0, 0}:: El.
+ result = loop fold(input->el:: Pair, {0, resultInit}->acc):: {idx:: int, max:: El}
+ {
+ density = el[0] / el[1] :: int.
+ idxNext = acc["idx"] + 1:: int.
+ elCur = {acc["idx"], density}:: El.
+
+ {idxNext, maxEl(elCur, acc["max"])}:: {idx:: int, max:: El}
+ }.
+
+ result["max"]
+}
+
+fn-minmax6 = function:: Pair
+{
+ arr = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+
+ init = {0, {{1000, 1000}, {0, 0}}}:: {int, PairEl}.
+
+ result = loop fold(arr->val:: int, init->acc):: {int, PairEl}
+ {
+ el = {acc[0], val}:: El.
+
+ idx = acc[0]+1 :: int.
+ min = minEl(el, acc[1, 0]) :: El.
+ max = maxLstEl(el, acc[1, 1]):: El.
+
+ {idx, ({min, max}:: PairEl)}:: {int, PairEl}
+ }.
+
+ {result[1][0]["idx"], result[1][1]["idx"]}
+}
+
+fn-minmax7 = function:: Pair
+{
+ arr = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+
+ init = {0, {{0, 0}, {1000, 1000}}}:: {int, PairEl}.
+
+ result = loop fold(arr->val:: int, init->acc):: {int, PairEl}
+ {
+ el = {acc[0], val}:: El.
+
+ idx = acc[0]+1 :: int.
+ max = maxEl(el, acc[1, 0]) :: El.
+ min = minLstEl(el, acc[1, 1]):: El.
+
+ {idx, ({max, min}:: PairEl)}:: {int, PairEl}
+ }.
+
+ {result[1][0]["idx"], result[1][1]["idx"]}
+}
+
+fn-minmax8 = function:: Pair
+{
+ input = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+ init = {0, {{1000, 1000}, {1000, 1000}}}:: {int, PairEl}.
+
+ result = loop fold(input->val:: int, init->acc):: {int, PairEl}
+ {
+ el = {acc[0], val}:: El.
+ idx = acc[0]+1 :: int.
+ minF = minEl(el, acc[1, 0]) :: El.
+ minL = minLstEl(el, acc[1, 1]):: El.
+
+ {idx, {minF, minL}}:: {int, PairEl}
+ }.
+
+ {result[1, 0, "idx"], result[1, 1, "idx"]}
+}
+
+fn-minmax9 = function:: Pair
+{
+ input = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+ init = {0, {{0, 0}, {0, 0}}}:: {int, PairEl}.
+
+ result = loop fold(input->val:: int, init->acc):: {int, PairEl}
+ {
+ el = {acc[0], val}:: El.
+ idx = acc[0]+1 :: int.
+ maxF = maxEl(el, acc[1, 0]) :: El.
+ maxL = maxLstEl(el, acc[1, 1]):: El.
+
+ {idx, {maxF, maxL}}:: {int, PairEl}
+ }.
+
+ {result[1, 0, "idx"], result[1, 1, "idx"]}
+}
+
+fn-minmax10 = function:: int
+{
+ input = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+ init = {0, {{1000, 1000}, {0, 0}}}:: {int, PairEl}.
+
+ result = loop fold(input->val:: int, init->acc):: {int, PairEl}
+ {
+ el = {acc[0], val}:: El.
+ idx = acc[0]+1 :: int.
+ minF = minEl(el, acc[1, 0]) :: El.
+ maxF = maxEl(el, acc[1, 1]):: El.
+
+ {idx, {minF, maxF}}:: {int, PairEl}
+ }.
+
+ (minElIdx(result[1, 0], result[1, 1])::El)["idx"]
+}
+
+fn-minmax11 = function:: int
+{
+ input = {25, 37, 1, 1, 6, 5, 19, 3, 37, 20}:: [int].
+
+ ctxInit = {0, {{1000, 1000}, {0, 0}}}:: {int, PairEl}.
+ result = loop fold(input-> val:: int, ctxInit->ctx):: {int, PairEl}
+ {
+ elCur = {ctx[0], val}:: El.
+
+ elMinL = minLstEl(elCur, ctx[1, 0]):: El.
+ elMaxL = maxLstEl(elCur, ctx[1, 1]):: El.
+
+ {ctx[0]+1, {elMinL, elMaxL}}:: {int, PairEl}
+ }.
+
+ (maxElIdx(result[1, 0], result[1, 1])::El)["idx"]
+}
+
+fn-minmax12 = function:: int
+{
+ input = {-8, 16, 3, -5, 2, -11, -905, -54}:: [int].
+
+ loop fold(input->val:: int, 0->minPos):: int
+ {
+ if (val > 0 { min(val, minPos) } else { minPos }
+ }
+}
diff --git a/scripts/dfa/build-table.xreate b/scripts/dfa/build-table.xreate
new file mode 100644
index 0000000..90deb77
--- /dev/null
+++ b/scripts/dfa/build-table.xreate
@@ -0,0 +1,22 @@
+Tree = type(NodeData) variant {
+ LEAF(data:: NodeData),
+ GROUP(nodes:: [ref(Tree(NodeData))])
+}
+
+Guard = type variant {
+ a, b
+}.
+
+DecisionTree = type Tree(Guard).
+
+buildTable = function(nodes:: [DecisionTree], size:: i32):: [ DecisionTree ]
+{
+ tableInit = arr_create(size):: [DecisionTree].
+
+ loop fold(nodes->node:: DecisionTree, tableInit->table):: [DecisionTree]
+ {
+ switch variant(node):: [DecisionTree]
+ case (LEAF) { table + { LEAF(node["data"]) } }
+ case (GROUP) { table + GROUP(buildTable(nodes["nodes"])) }
+ }
+}
diff --git a/scripts/execution-order/test-1.xreate b/scripts/execution-order/test-1.xreate
index 239d1a8..2f4dee5 100644
--- a/scripts/execution-order/test-1.xreate
+++ b/scripts/execution-order/test-1.xreate
@@ -1,49 +1,49 @@
// UnitTest: tests/exploitation.cpp, Exploitation.Doc_ExampleEov_1
interface(extern-c){
externalLibs = library:: pkgconfig("libxml-2.0").
include {
externalLibs = {"scripts/virtualization/defs.h"}
}.
}
<insert ExampleEov_1_Specializations>
print = function(content:: Content):: int
{
switch variant(content):: int
- case (errcode) {content}
- case (message) {printf("%s", content)}
+ case (errcode) {content["data"]}
+ case (message) {printf("%s", content["data"])}
}
sendResponse = function(header:: Content, body:: Content, footer:: Content):: int
{
seq
{print(header)}
{print(body)}
{print(footer)}
}
main = function:: int; entry
{
seq
{
header = send("Header"):: Content; eov_checkpoint(webpage, header).
header
}
{
body = send("Body"):: Content; eov_checkpoint(webpage, body).
body
}
{
footer = send("Footer"):: Content; eov_checkpoint(webpage, footer).
footer
}
{
sendResponse(header, body, footer)
}
}

Event Timeline