No OneTemporary

File Metadata

Created
Sun, Feb 15, 11:42 PM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.gitignore b/.gitignore
index 59de723..c7edac1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,84 +1,83 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*-build-*
# QtCreator
*.autosave
coco/*.old
coco/*~
*~
-
+# XREATE
cpp/build-*/*
cpp/xreate-debug/*
cpp/xreate-release/*
cpp/.idea
CMakeLists.txt.user
cmake_install.cmake
project/*
nb*.xml
.*
target/*
/tools/phabricator/xreate-frontend/nbproject/private/
documentation/trash4/
trash/
CMakeFiles/
gen-cpp/
generated-cpp/
gen-php/
generated-js/
books/
build/
coco/Parser.*
coco/Scanner.*
tools/phabricator/administration/
-scripts/**/tmp-*
+**/tmp-*
cpp/tests/vendorsAPI/
-
diff --git a/config/default.json b/config/default.json
index 90aa4c0..e2db4c2 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,74 +1,74 @@
{
"containers": {
"id": {
"implementations": "containers_impl",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
"onthefly": "on_the_fly"
}
},
"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": "documentation",
+ "template": "troubleshooting",
"templates": {
- "troubleshooting":"Transcend.Doc_*",
- "documentation":"Modules.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*",
+ "troubleshooting":"ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*",
+ "documentation":"Modules.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*",
"default": "*",
"ast": "AST.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"compilation": "Compilation.*",
"communication": "Communication.*",
"cfa": "CFA.*",
"containers": "Containers.*",
"dfa": "DFA.*",
"diagnostic": "Diagnostic.*",
"dsl": "Association.*:Interpretation.*",
"exploitation": "Exploitation.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"loops": "Loop.*",
"latereasoning": "LateReasoning.*",
"latex": "Latex.*",
"modules": "Modules.*",
"polymorphs": "Polymorphs.*",
"intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*",
"types": "Types.*",
"virtualization": "Virtualization.*",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2.*"
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 93ad47b..cb91525 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,236 +1,238 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
message(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS})
execute_process(
COMMAND llvm-config --libs
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# POTASSCO
#======================
set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
${POTASSCO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/)
set(COCO_SOURCE_FILES_MAIN
${COCO_GRAMMAR_PATH}/main/Parser.cpp
${COCO_GRAMMAR_PATH}/main/Scanner.cpp
)
set(COCO_SOURCE_FILES_MODULES
${COCO_GRAMMAR_PATH}/modules/Parser.cpp
${COCO_GRAMMAR_PATH}/modules/Scanner.cpp
)
set(COCO_SOURCE_FILES ${COCO_SOURCE_FILES_MODULES} ${COCO_SOURCE_FILES_MAIN})
INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH})
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MAIN}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar main ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG
)
add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MODULES}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar modules ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/modules.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
set(SOURCE_FILES
+ analysis/temporalseqgraph.cpp
+ pass/cfatemporalseqpass.cpp
+ analysis/cfagraph.cpp
+ pass/cfapass.cpp
modules.cpp
- analysis/DominatorsAnalysisProvider.cpp
compilation/interpretation-instructions.cpp
ExternLayer.cpp
analysis/cfagraph.cpp
compilation/latereasoning.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
- pass/cfapass.cpp
contextrule.cpp
query/containers.cpp
aux/serialization/expressionserializer.cpp
)
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
add_library(${PROJECT_NAME} SHARED ${COCO_SOURCE_FILES} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
message("definitions all: " ${DEFINITIONS_ALL})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL})
get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
message("compilations all: " ${COMPILATION_OPTIONS_ALL})
target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL})
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY
INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb boost_system boost_filesystem
)
#${CLANG_LIBS}
#set (LINK_INTERFACE_LIBRARIES "")
# FUNCTION(PREPEND var prefix)
# SET(listVar "")
# FOREACH(f ${ARGN})
# LIST(APPEND listVar "${prefix}/${f}")
# ENDFOREACH(f)
# SET(${var} "${listVar}" PARENT_SCOPE)
# ENDFUNCTION(PREPEND)
#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
#cotire(xreate)
# MACRO (ADD_PCH_RULE _header_filename _src_list)
# SET(_gch_filename "${_header_filename}.gch")
# LIST(APPEND ${_src_list} ${_gch_filename})
# SET (_args ${CMAKE_CXX_FLAGS})
# LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename})
# GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
# foreach (_inc ${DIRINC})
# LIST(APPEND _args "-I" ${_inc})
# endforeach(_inc ${DIRINC})
# SEPARATE_ARGUMENTS(_args)
# add_custom_command(OUTPUT ${_gch_filename}
# COMMAND rm -f ${_gch_filename}
# COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
# DEPENDS ${_header_filename})
# ENDMACRO(ADD_PCH_RULE _header_filename _src_list)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES)
# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES)
diff --git a/cpp/src/analysis/DominatorsAnalysisProvider.cpp b/cpp/src/analysis/DominatorsAnalysisProvider.cpp
deleted file mode 100644
index 57b24f0..0000000
--- a/cpp/src/analysis/DominatorsAnalysisProvider.cpp
+++ /dev/null
@@ -1,284 +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: DominatorsAnalysisProvider.cpp
- * Author: pgess <v.melnychenko@xreate.org>
- *
- * Created on May 13, 2016, 11:39 AM
- */
-
-/**
- * \file DominatorsAnalysisProvider.h
- * \brief Dominators Tree analysis
- */
-
-#include "analysis/cfagraph.h"
-#include "analysis/DominatorsAnalysisProvider.h"
-
-#include "llvm/ADT/GraphTraits.h"
-#include "llvm/Support/GenericDomTreeConstruction.h"
-#include "llvm/Support/GenericDomTree.h"
-
-#include <list>
-#include <iostream>
-#include <boost/format.hpp>
-
-using namespace std;
-using namespace xreate;
-using namespace boost;
-using namespace boost::bimaps;
-
-namespace xreate { namespace dominators {
-
-struct CFAGraphAdapter;
-
-struct ScopeNode {
- ScopePacked id;
- CFAGraphAdapter* parent;
- std::list<ScopeNode*> nodesFrom;
- std::list<ScopeNode*> nodesTo;
-
- CFAGraphAdapter* getParent(){ return parent; }
- void printAsOperand(llvm::raw_ostream&, bool) {}
- ScopeNode(ScopePacked scope, CFAGraphAdapter* parentAdapter):
- id(scope), parent(parentAdapter) {}
-};
-
-}
-} //end of namespace xreate::dominators
-
-namespace llvm {
-using namespace xreate::dominators;
-
-template<>
-struct GraphTraits<ScopeNode*> {
- typedef ScopeNode* NodeRef;
- typedef std::list<ScopeNode*>::iterator ChildIteratorType;
-
- static ChildIteratorType
- child_begin(ScopeNode* node) {
- return node->nodesTo.begin();
- }
-
- static ChildIteratorType
- child_end(ScopeNode* node) {
- return node->nodesTo.end();
- }
-};
-
-template<>
-struct GraphTraits<Inverse<ScopeNode*>>
-{
- typedef ScopeNode* NodeRef;
- typedef std::list<ScopeNode*>::iterator ChildIteratorType;
-
- static ChildIteratorType
- child_begin(ScopeNode* node) {
- return node->nodesFrom.begin();
- }
-
- static ChildIteratorType
- child_end(ScopeNode* node) {
- return node->nodesFrom.end();
- }
-};
-
-template<>
-struct GraphTraits<CFAGraphAdapter*> {
- typedef std::list<ScopeNode*>::iterator nodes_iterator;
-
- static nodes_iterator
- nodes_begin(CFAGraphAdapter* graph) {
- return graph->nodes.begin();
- }
-
- static nodes_iterator
- nodes_end(CFAGraphAdapter* graph) {
- return graph->nodes.end();
- }
-
- static ScopeNode*
- getEntryNode(CFAGraphAdapter* F) {
- return F->nodeRoot;
- }
-
- static unsigned int
- size(CFAGraphAdapter* graph) {
- return graph->nodes.size();
- }
-
- static nodes_iterator
- child_begin(ScopeNode* node) {
- return node->nodesTo.begin();
- }
-
- static nodes_iterator
- child_end(ScopeNode* node) {
- return node->nodesTo.end();
- }
-};
-}
-
-namespace xreate {
-namespace dominators {
-
-class DominatorTree : public llvm::DominatorTreeBase<ScopeNode, false> {
-friend class DominatorsAnalysisProvider;
-public:
- DominatorTree() : llvm::DominatorTreeBase<ScopeNode, false>() {}
-
- void
- run(CFAGraphAdapter& program) {
- recalculate(program);
- updateDFSNumbers();
-
- //extract dominators info
- for(auto& entry : DomTreeNodes) {
- if(!entry.getFirst()) continue;
-
- dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
- }
- }
-
- void
- print(std::ostringstream& output, const std::string& atom) const {
- boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
-
- for(auto entry : dominators) {
- output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
- <<std::endl;
- }
- }
-
-private:
- DominatorsAnalysisProvider::Dominators dominators;
-};
-
-class PostDominatorTree : public llvm::DominatorTreeBase<ScopeNode, true> {
-friend class DominatorsAnalysisProvider;
-public:
- PostDominatorTree() : llvm::DominatorTreeBase<ScopeNode, true>() {}
-
- void
- run(CFAGraphAdapter& program) {
- recalculate(program);
- updateDFSNumbers();
- //extract dominators info
- for(auto& entry : DomTreeNodes) {
- if(!entry.getFirst()) continue;
-
- dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
- }
- }
-
- void
- print(std::ostringstream& output, const std::string& atom) const {
- boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
-
- for(auto entry : dominators) {
- output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
- <<std::endl;
- }
- }
-
-private:
- DominatorsAnalysisProvider::Dominators dominators;
-};
-
-ScopeNode*
-CFAGraphAdapter::registerScope(ScopePacked scope){
- ScopeNode elemNew(scope, this);
- auto fnComp = [](const ScopeNode* a, const ScopeNode* b){return a->id < b->id;};
- auto posLowerBound = std::lower_bound(nodes.begin(), nodes.end(), &elemNew, fnComp);
-
- if(posLowerBound==nodes.end()|| (*posLowerBound)->id > scope){
- ScopeNode* elemNewP = new ScopeNode(elemNew);
- *elemNewP = elemNew;
- return *nodes.insert(posLowerBound, elemNewP);
- }
-
- return *posLowerBound;
-}
-
-CFAGraphAdapter*
-CFAGraphAdapter::build(const cfa::CFAGraph* graph) {
- return build(graph->__dependencyRelations);
-}
-
-CFAGraphAdapter*
-CFAGraphAdapter::build(const std::multimap<ScopePacked, ScopePacked>& dataScopesOrder){
- CFAGraphAdapter* tree=new CFAGraphAdapter();
-
- enum NODE_MARK{NO_ROOT, POSSIBLE_ROOT};
- std::unordered_map<unsigned int, NODE_MARK> nodeMarks;
- for (const auto& edge: dataScopesOrder){
-
- ScopeNode* nodeTo = tree->registerScope(edge.first);
- ScopeNode* nodeFrom = tree->registerScope(edge.second);
- nodeTo->nodesFrom.push_back(nodeFrom);
- nodeFrom->nodesTo.push_back(nodeTo);
-
- nodeMarks.emplace(edge.second, POSSIBLE_ROOT); //weak optional insert
- auto result = nodeMarks.emplace(edge.first, NO_ROOT); //strong insert or update
- if(!result.second){
- result.first->second = NO_ROOT;
- }
- }
-
- std::list<ScopePacked> nodeRoots;
- for(auto nodeMark: nodeMarks){
- if(nodeMark.second == POSSIBLE_ROOT) nodeRoots.push_back(nodeMark.first);
- }
-
- if(nodeRoots.size()>1){
- ScopeNode* nodeGlobalRoot = tree->registerScope(SCOPE_ABSTRACT_GLOBAL);
- for(auto rootLocal: nodeRoots){
- ScopeNode* nodeLocalRoot = tree->registerScope(rootLocal);
- nodeLocalRoot->nodesFrom.push_back(nodeGlobalRoot);
- nodeGlobalRoot->nodesTo.push_back(nodeLocalRoot);
- }
-
- tree->nodeRoot = nodeGlobalRoot;
-
- } else if (nodeRoots.size()==1){
- tree->nodeRoot = tree->registerScope(nodeRoots.front());
-
- } else {
- ScopeNode* nodeGlobalRoot = tree->registerScope(SCOPE_ABSTRACT_GLOBAL);
- tree->nodeRoot = nodeGlobalRoot;
- }
-
- return tree;
-}
-
-void
-DominatorsAnalysisProvider::run(CFAGraphAdapter* program) {
- treeForwardDominators.reset(new DominatorTree());
- treePostDominators.reset(new PostDominatorTree());
-
- treeForwardDominators->run(*program);
- treePostDominators->run(*program);
-}
-
-void
-DominatorsAnalysisProvider::print(std::ostringstream& output) const {
- treeForwardDominators->print(output, "cfa_forwdom");
- treePostDominators->print(output, "cfa_postdom");
-}
-
-const DominatorsAnalysisProvider::Dominators&
-DominatorsAnalysisProvider::getForwardDominators() const {
- return treeForwardDominators->dominators;
-}
-
-const DominatorsAnalysisProvider::Dominators&
-DominatorsAnalysisProvider::getPostDominators() const {
- return treePostDominators->dominators;
-}
-
-DominatorsAnalysisProvider::DominatorsAnalysisProvider() {}
-DominatorsAnalysisProvider::~DominatorsAnalysisProvider() { }
-
-
-}} //end of namespace xreate::dominators
diff --git a/cpp/src/analysis/DominatorsAnalysisProvider.h b/cpp/src/analysis/DominatorsAnalysisProvider.h
deleted file mode 100644
index a7124cc..0000000
--- a/cpp/src/analysis/DominatorsAnalysisProvider.h
+++ /dev/null
@@ -1,56 +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: DominatorsAnalysisProvider.h
- * Author: pgess <v.melnychenko@xreate.org>
- *
- * Created on May 13, 2016, 11:39 AM
- */
-
-#ifndef DominatorsAnalysisProvider_H
-#define DominatorsAnalysisProvider_H
-
-#include "transcendlayer.h"
-#include <boost/smart_ptr/scoped_ptr.hpp>
-
-namespace xreate{namespace dominators{
-
-class DominatorTree;
-class PostDominatorTree;
-class ScopeNode;
-
-struct CFAGraphAdapter {
- std::list<ScopeNode*> nodes;
- ScopeNode* nodeRoot;
-
- ScopeNode* registerScope(ScopePacked scope);
- static CFAGraphAdapter* build(const cfa::CFAGraph* graph);
- static CFAGraphAdapter* build(const std::multimap<ScopePacked, ScopePacked>& dataScopesOrder);
- CFAGraphAdapter() { }
-};
-
-/** \brief Dominators Analysis report */
-class DominatorsAnalysisProvider: public IAnalysisReport {
-public:
- typedef std::pair<ScopePacked, ScopePacked> DominatedRange;
- typedef std::map<ScopePacked, DominatedRange> Dominators;
-
- DominatorsAnalysisProvider();
- virtual ~DominatorsAnalysisProvider();
-
- void run(CFAGraphAdapter* program);
- void print(std::ostringstream& output) const override;
-
- const Dominators& getForwardDominators() const;
- const Dominators& getPostDominators() const;
-
-private:
- boost::shared_ptr<DominatorTree> treeForwardDominators;
- boost::shared_ptr<PostDominatorTree> treePostDominators;
-};
-
-}} //end of namespace xreate::dominators
-
-#endif /* DominatorsAnalysisProvider_H */
-
diff --git a/cpp/src/analysis/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp
index df29784..ef0c679 100644
--- a/cpp/src/analysis/cfagraph.cpp
+++ b/cpp/src/analysis/cfagraph.cpp
@@ -1,220 +1,191 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
/**
* \file cfagraph.h
* \brief Control Flow Analysis(CFA) graph data
- *
*/
#include "analysis/cfagraph.h"
#include "analysis/utils.h"
using namespace xreate::cfa;
using namespace std;
void
CFAGraph::print(std::ostringstream& output) const {
- const std::string& atomBinding = Config::get("transcend.bindings.function");
- const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
-
- output << endl << "%\t\tStatic analysis: CFA" << endl;
- output << __outputPrecomputed.str();
-
- //show function tags
- int counterTags = 0;
- std::ostringstream bufFunctionNames;
- boost::format formatFunction("function(%1%).");
- boost::format formatBind(atomBinding + "(%1%, %2%).");
- for (auto function : this->__nodesFunction.left) {
- const auto tags = this->__functionTags.equal_range(function.first);
- if (tags.first == tags.second) {
- //no tags
- bufFunctionNames << "; " << function.second ;
- continue;
- }
-
- output << formatFunction % (function.second) << std::endl;
- for (const auto& tag_ : boost::make_iterator_range(tags)) {
- const Expression& tag = tag_.second;
-
- list<string> tagRaw = xreate::analysis::compile(tag);
- assert(tagRaw.size() == 1);
-
- output << formatBind
- % (function.second)
- % (tagRaw.front())
- << endl;
- ++counterTags;
- }
- }
-
- if (bufFunctionNames.tellp()) {
- output << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
- }
-
- if (counterTags == 0) {
- output << "%no 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->__parentFunctionRelations) {
- const string& function = this->__nodesFunction.left.at(relation.right);
-
- output << formatFunctionParent % relation.left % function << endl;
- }
-
- //TOTEST CFG parent scope
- boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
- for (const auto &relation : this->__parentScopeRelations) {
- output << formatScopeParent % relation.first % relation.second << endl;
- }
-
- //call connections
- boost::format formatCall("cfa_call(%1%, %2%).");
-
- for (const auto &relation : this->__callRelations) {
- const ScopePacked scopeFrom = relation.left;
- const string& functionTo = this->__nodesFunction.left.at(relation.right);
-
- output << formatCall % (scopeFrom) % (functionTo) << endl;
- }
-
- //function specializations 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;
- }
- }
-
- //Dependencies
- boost::format formatDependencies("cfa_scope_depends(%1%, %2%).");
- for(const auto relation : __dependencyRelations) {
- output << formatDependencies % relation.first % relation.second << endl;
- }
- std::multimap<ScopePacked, ScopePacked> __dependencyRelations;
+ const std::string& atomBinding = Config::get("transcend.bindings.function");
+ const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
+
+ output << endl << "%\t\tStatic analysis: CFA" << endl;
+ output << __outputPrecomputed.str();
+
+ //show function tags
+ int counterTags = 0;
+ std::ostringstream bufFunctionNames;
+ boost::format formatFunction("function(%1%).");
+ boost::format formatBind(atomBinding + "(%1%, %2%).");
+ for (auto function : this->__fnNodes.left) {
+ const auto tags = this->__fnTags.equal_range(function.first);
+ if (tags.first == tags.second) {
+ //no tags
+ bufFunctionNames << "; " << function.second ;
+ continue;
+ }
+
+ output << formatFunction % (function.second) << std::endl;
+ for (const auto& tag_ : boost::make_iterator_range(tags)) {
+ const Expression& tag = tag_.second;
+
+ list<string> tagRaw = xreate::analysis::compile(tag);
+ assert(tagRaw.size() == 1);
+
+ output << formatBind
+ % (function.second)
+ % (tagRaw.front())
+ << endl;
+ ++counterTags;
+ }
+ }
+
+ if (bufFunctionNames.tellp()) {
+ output << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
+ }
+
+ if (counterTags == 0) {
+ output << "%no function tags at all" << endl;
+ }
+
+ //declare scopes
+ boost::format formatScope("scope(0..%1%).");
+ output << formatScope % (__transcend->getScopesCount() - 1) << std::endl;
+
+ //show context rules:
+ for (auto rule : this->__contextRules) {
+ output << ContextRule(rule.second).compile(rule.first) << std::endl;
+ };
+
+ //show scope tags:
+ counterTags = 0;
+ boost::format formatScopeBind(atomBindingScope + "(%1%, %2%, strong).");
+ for (auto entry : this->__scopeTags) {
+ ScopePacked scopeId = entry.first;
+ const Expression& tag = entry.second;
+ list<string> tagRaw = xreate::analysis::compile(tag);
+ assert(tagRaw.size() == 1);
+
+ output << formatScopeBind % scopeId % (tagRaw.front()) << endl;
+ ++counterTags;
+ }
+
+ if (counterTags == 0) {
+ output << "%scope tags: no tags at all" << endl;
+ }
+
+ //parent connections
+ //TOTEST CFG parent function
+ boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
+ for (const auto &relation : this->__parentFnRelation) {
+ const string& function = this->__fnNodes.left.at(relation.right);
+
+ output << formatFunctionParent % relation.left % function << endl;
+ }
+
+ //TOTEST CFG parent scope
+ boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
+ for (const auto &relation : this->__parentScopeRelation) {
+ output << formatScopeParent % relation.first % relation.second << endl;
+ }
+
+ //call connections
+ boost::format formatCall("cfa_call(%1%, %2%).");
+
+ for (const auto &relation : this->__callRelations) {
+ const ScopePacked scopeFrom = relation.left;
+ const string& functionTo = this->__fnNodes.left.at(relation.right);
+
+ output << formatCall % (scopeFrom) % (functionTo) << endl;
+ }
+
+ //function specializations description
+ boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
+ const list<ManagedFnPtr>& functions = __transcend->ast->getAllFunctions();
+ for (auto f : functions) {
+ if (f->guard.isValid()) {
+ list<string> guardRaw = xreate::analysis::compile(f->guard);
+ assert(guardRaw.size() == 1);
+ output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
+ }
+ }
}
void
-CFAGraph::addFunctionAnnotations(const std::string& function, const std::map<std::string, Expression>& tags) {
- unsigned int fid = registerNodeFunction(function);
+CFAGraph::addFunctionAnnotations(const std::string& fn, const std::map<std::string, Expression>& tags) {
+ unsigned int fid = registerNodeFunction(fn);
- for (auto& tag : tags) {
- __functionTags.emplace(fid, tag.second);
- }
+ 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);
- }
+ 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);
- }
+ for (Expression rule : rules) {
+ __contextRules.emplace(scope, rule);
+ }
}
void
-CFAGraph::addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo) {
- unsigned int idFuncTo = registerNodeFunction(functionTo);
+CFAGraph::addCallConnection(const ScopePacked& callerScope, const std::string& calleeFn) {
+ unsigned int idFuncTo = registerNodeFunction(calleeFn);
- __callRelations.insert(CALL_RELATIONS::value_type(scopeFrom, idFuncTo));
+ __callRelations.insert(CALL_RELATIONS::value_type(callerScope, idFuncTo));
}
void
-CFAGraph::addParentConnection(const ScopePacked& scope, const std::string& functionParent) {
- __parentFunctionRelations.insert(PARENT_FUNCTION_RELATIONS::value_type(scope, registerNodeFunction(functionParent)));
+CFAGraph::addParentConnection(const ScopePacked& scopeEntry, const std::string& fnParent) {
+ __parentFnRelation.insert(PARENT_FUNCTION_RELATIONS::value_type(scopeEntry, registerNodeFunction(fnParent)));
}
void
-CFAGraph::addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent) {
- __parentScopeRelations.emplace(scope, scopeParent);
+CFAGraph::addParentConnection(const ScopePacked& scopeChild, const ScopePacked& scopeParent) {
+ __parentScopeRelation.emplace(scopeChild, scopeParent);
}
unsigned int
CFAGraph::registerNodeFunction(const std::string& fname) {
- auto pos = __nodesFunction.left.insert(make_pair(__nodesFunction.size(), fname));
-
- return pos.first->first;
-}
-
-void
-CFAGraph::addDependency(const ScopePacked& scope, const ScopePacked& scopeDependency) {
- __dependencyRelations.emplace(scope, scopeDependency);
-}
-
-bool
-CFAGraph::isDependent(const ScopePacked& scope) const {
- return __dependencyRelations.count(scope) > 0;
-}
-
-void
-CFAGraph::transmitDependencies(const ScopePacked& scopeTo, const ScopePacked& scopeFrom) {
- auto range = __dependencyRelations.equal_range(scopeFrom);
+ auto pos = __fnNodes.left.insert(make_pair(__fnNodes.size(), fname));
- std::list<ScopePacked> dependencies;
- for (auto pairI = range.first; pairI != range.second; ++pairI) {
- dependencies.push_back(pairI->second);
- }
-
- for(auto dep : dependencies) {
- __dependencyRelations.emplace(scopeTo, dep);
- }
+ return pos.first->first;
}
void
CFAGraph::addScope(CodeScope* scope) {
- boost::format formatScopeBinding("ast_scope_binding(%1%, %2%, \"%3%\").");
-
- ScopePacked scopeId = __transcend->pack(scope);
- for (int id=0, size = scope->__bindings.size(); id < size; ++id) {
- __outputPrecomputed << formatScopeBinding
- % scopeId
- % id
- % scope->__bindings.at(id)
- << endl;
- }
+ boost::format formatScopeBinding("ast_scope_binding(%1%, %2%, \"%3%\").");
+
+ ScopePacked scopeId = __transcend->pack(scope);
+ __scopesCount = max(scopeId + 1, __scopesCount);
+
+ for (int id = 0, size = scope->__bindings.size(); id < size; ++id) {
+ __outputPrecomputed << formatScopeBinding
+ % scopeId
+ % id
+ % scope->__bindings.at(id)
+ << endl;
+ }
}
+
diff --git a/cpp/src/analysis/cfagraph.h b/cpp/src/analysis/cfagraph.h
index a4e1dc4..543731a 100644
--- a/cpp/src/analysis/cfagraph.h
+++ b/cpp/src/analysis/cfagraph.h
@@ -1,64 +1,66 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
#ifndef CFAGRAPH_H
#define CFAGRAPH_H
#include "transcendlayer.h"
-namespace xreate {namespace cfa {
-
- /** \brief Represents CFA analysis data produced by CFAPass */
- class CFAGraph: public IAnalysisReport {
- public:
- typedef boost::bimap<ScopePacked, boost::bimaps::multiset_of<unsigned int>> PARENT_FUNCTION_RELATIONS;
- PARENT_FUNCTION_RELATIONS __parentFunctionRelations;
- std::map<ScopePacked, ScopePacked> __parentScopeRelations;
- std::multimap<ScopePacked, ScopePacked> __dependencyRelations;
-
- typedef boost::bimap<
- boost::bimaps::multiset_of<ScopePacked>,
- boost::bimaps::multiset_of<unsigned int>,
- boost::bimaps::set_of_relation<>
- > CALL_RELATIONS;
-
- CALL_RELATIONS __callRelations;
-
- boost::bimap<unsigned int, std::string > __nodesFunction;
- std::multimap<unsigned int, Expression> __functionTags;
- std::multimap<ScopePacked, Expression> __scopeTags;
- std::multimap<ScopePacked, ContextRule> __contextRules;
-
- void print(std::ostringstream& output) const override;
- CFAGraph(TranscendLayer* engine): __transcend(engine){}
-
- void addFunctionAnnotations(const std::string& function, const std::map<std::string, Expression>& tags);
- void addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>&tags);
- void addContextRules(const ScopePacked& scope, const std::vector<Expression>&rules);
- void addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo);
- void addParentConnection(const ScopePacked& scope, const std::string& functionParent);
- void addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent);
- void addDependency(const ScopePacked& scope, const ScopePacked& scopeDependency);
- bool isDependent(const ScopePacked& scope) const;
- void transmitDependencies(const ScopePacked& scopeTo, const ScopePacked& scopeFrom);
- void addScope(CodeScope* scope);
-
- private:
- TranscendLayer* __transcend;
- std::ostringstream __outputPrecomputed;
-
- unsigned int registerNodeFunction(const std::string& fname);
-
- };
-
-}} //end of namespace xreate::cfa
+namespace xreate{
+namespace cfa{
+
+/** \brief Represents CFA analysis data produced by CFAPass */
+class CFAGraph: public IAnalysisReport{
+ friend class TemporalSeqGraph;
+public:
+ typedef boost::bimap<ScopePacked, boost::bimaps::multiset_of<unsigned int>> PARENT_FUNCTION_RELATIONS;
+ PARENT_FUNCTION_RELATIONS __parentFnRelation;
+ std::map<ScopePacked, ScopePacked> __parentScopeRelation;
+
+ typedef boost::bimap<
+ boost::bimaps::multiset_of<ScopePacked>,
+ boost::bimaps::multiset_of<unsigned int>,
+ boost::bimaps::set_of_relation<>
+ > CALL_RELATIONS;
+
+ CALL_RELATIONS __callRelations;
+
+ boost::bimap<unsigned int, std::string> __fnNodes;
+ std::multimap<unsigned int, Expression> __fnTags;
+ std::multimap<ScopePacked, Expression> __scopeTags;
+ std::multimap<ScopePacked, ContextRule> __contextRules;
+ unsigned int __scopesCount = 0;
+
+ void print(std::ostringstream &output) const override;
+
+ CFAGraph(TranscendLayer* engine): __transcend(engine){ }
+
+ void addFunctionAnnotations(const std::string &fn, const std::map<std::string, Expression> &tags);
+ void addScopeAnnotations(const ScopePacked &scope, const std::vector<Expression> &tags);
+ void addContextRules(const ScopePacked &scope, const std::vector<Expression> &rules);
+ void addCallConnection(const ScopePacked &callerScope, const std::string &calleeFn);
+ void addParentConnection(const ScopePacked &scopeEntry, const std::string &fnParent);
+ void addParentConnection(const ScopePacked &scopeChild, const ScopePacked &scopeParent);
+ void addScope(CodeScope* scope);
+
+private:
+ TranscendLayer* __transcend;
+ std::ostringstream __outputPrecomputed;
+
+ unsigned int registerNodeFunction(const std::string &fname);
+};
+
+
+
+}
+} //end of namespace xreate::cfa
#endif /* CFAGRAPH_H */
diff --git a/cpp/src/analysis/temporalseqgraph.cpp b/cpp/src/analysis/temporalseqgraph.cpp
new file mode 100644
index 0000000..47a09d7
--- /dev/null
+++ b/cpp/src/analysis/temporalseqgraph.cpp
@@ -0,0 +1,219 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * File: temporalseqgraph.cpp
+ * Author: pgess
+ *
+ * Created on February 4, 2019, 4:51 PM
+ */
+
+#include "temporalseqgraph.h"
+
+using namespace xreate::cfa;
+using namespace std;
+
+namespace std {
+ bool operator<(const xreate::cfa::TemporalNode& x, const xreate::cfa::TemporalNode& y) {
+ if(x.scope != y.scope) return x.scope < y.scope;
+ return x.mark < y.mark;
+ }
+};
+
+TemporalSeqGraph::TemporalSeqGraph(TranscendLayer* transcend)
+: __transcend(transcend) { }
+
+void
+TemporalSeqGraph::addSubScopes(const CodeScope* scopeIn, const std::list<CodeScope*>& scopesChild) {
+ auto socket = addSocket(scopeIn, TemporalOperator::AND);
+
+ for(auto scopeChild : scopesChild) {
+ TemporalNode nodeChild = TemporalNode{__transcend->pack(scopeChild), TemporalOperator::SCOPE};
+ connect(socket.first, nodeChild);
+ connect(nodeChild, socket.second);
+ }
+}
+
+void
+TemporalSeqGraph::addBranchScopes(const CodeScope* scopeIn, const std::list<CodeScope*>& scopesChild) {
+ auto socket = addSocket(scopeIn, TemporalOperator::AND);
+ TemporalNode toNode{__idNextVacant++, TemporalOperator::OR};
+ connect(toNode, socket.second);
+
+ for(auto scopeChild : scopesChild) {
+ TemporalNode nodeChild = TemporalNode{__transcend->pack(scopeChild), TemporalOperator::SCOPE};
+ connect(socket.first, nodeChild);
+ connect(nodeChild, toNode);
+ }
+}
+
+std::pair<TemporalNode, TemporalNode>
+TemporalSeqGraph::addSocket(const CodeScope* scopeIn, TemporalOperator mark) {
+ TemporalNode nodeFrom;
+ TemporalNode nodeIn = TemporalNode{__transcend->pack(scopeIn), TemporalOperator::SCOPE};
+
+ auto rangeInward = graph.right.equal_range(nodeIn);
+ size_t sizeInward = std::distance(rangeInward.first, rangeInward.second);
+
+ if (sizeInward == 1) {
+ //if scope has single inward connection
+ nodeFrom = rangeInward.first->second;
+
+ } else if (sizeInward > 1) {
+ //if scope has multy inward con:
+ nodeFrom = insertBefore(nodeIn, EMPTY);
+
+ } else {
+ //no inward connections:
+ nodeFrom = insertBefore(nodeIn, EMPTY);
+ }
+
+ TemporalNode nodeTo = insertAfter(nodeIn, mark);
+ return {nodeFrom, nodeTo};
+}
+
+Socket
+TemporalSeqGraph::getFnSocket(ManagedFnPtr calleeFn) {
+ if(__cacheFnSockets.count(calleeFn)) {
+ return __cacheFnSockets.at(calleeFn);
+ }
+
+ TemporalNode fromNode{__idNextVacant++, TemporalOperator::EMPTY};
+ TemporalNode toNode{__idNextVacant++, TemporalOperator::EMPTY};
+ Socket fnSock = make_pair(fromNode, toNode);
+ __cacheFnSockets.emplace(calleeFn, fnSock);
+
+ return fnSock;
+}
+
+Socket
+TemporalSeqGraph::getUncertainFnSocket(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates) {
+ if(__cacheUncertainFnSockets.count(calleeName)) {
+ return __cacheUncertainFnSockets.at(calleeName);
+ }
+
+ Socket fnSock;
+ if(candidates.size() == 0) {
+ //External Function
+ TemporalNode node{__idNextVacant++, TemporalOperator::EMPTY};
+ fnSock = make_pair(node, node);
+
+ } else {
+ //Multiple specializations
+ TemporalNode fromNode{__idNextVacant++, TemporalOperator::EMPTY};
+ TemporalNode toNode{__idNextVacant++, TemporalOperator::OR};
+ fnSock = make_pair(fromNode, toNode);
+
+ for (const ManagedFnPtr& candidate : candidates) {
+ Socket candidateSock = getFnSocket(candidate);
+ connect(fromNode, candidateSock.first);
+ connect(candidateSock.second, toNode);
+ }
+ }
+ __cacheUncertainFnSockets.emplace(calleeName, fnSock);
+
+ return fnSock;
+}
+
+TemporalNode
+TemporalSeqGraph::insertBefore(TemporalNode node, TemporalOperator mark) {
+ TemporalNode nodeNew{__idNextVacant++, mark};
+
+ auto nodesInRange = graph.right.equal_range(node);
+ list<TemporalNode> nodesIn;
+ for(auto nodeInIt = nodesInRange.first; nodeInIt != nodesInRange.second; ++nodeInIt) {
+ nodesIn.push_back(nodeInIt->second);
+ }
+
+ graph.right.erase(node);
+ for(auto nodeIn : nodesIn) {
+ connect(nodeIn, nodeNew);
+ }
+
+ connect(nodeNew, node);
+ return nodeNew;
+}
+
+TemporalNode
+TemporalSeqGraph::insertAfter(TemporalNode node, TemporalOperator mark) {
+ TemporalNode nodeNew{__idNextVacant++, mark};
+
+ auto nodesOutRange = graph.left.equal_range(node);
+ list<TemporalNode> nodesOut;
+ for(auto nodeOutIt = nodesOutRange.first; nodeOutIt != nodesOutRange.second; ++nodeOutIt) {
+ nodesOut.push_back(nodeOutIt->second);
+ }
+
+ graph.left.erase(node);
+ for(auto nodeOut : nodesOut) {
+ connect(nodeNew, nodeOut);
+ }
+
+ connect(node, nodeNew);
+ return nodeNew;
+}
+
+void
+TemporalSeqGraph::connect(TemporalNode nodeFrom, TemporalNode nodeTo) {
+ graph.insert(Graph::value_type(nodeFrom, nodeTo));
+}
+
+void
+TemporalSeqGraph::connectGuarded(const Socket& from, const Socket& to) {
+ unsigned int guard = __guardNextVacant++;
+
+ graphGuarded.emplace(from.first, make_pair(to.first, TemporalGuard{TemporalGuard::IN, guard}));
+ graphGuarded.emplace(to.second, make_pair(from.second, TemporalGuard{TemporalGuard::OUT, guard}));
+}
+
+void
+TemporalSeqGraph::print(std::ostringstream &output) const {
+ for (auto entry : graph) {
+ output
+ << "cfa_seq("
+ << entry.left << ", "
+ << entry.right << ").\n";
+ }
+
+ for (auto entry : graphGuarded) {
+ output
+ << "cfa_seq_guarded("
+ << entry.first << ", "
+ << entry.second.first << ", "
+ << (entry.second.second.mark == TemporalGuard::IN ? "in(" : "out(")
+ << entry.second.second.id << ")).\n";
+ }
+}
+
+bool TemporalSeqGraph::isOrdered(const ScopePacked& scopeAfter, const ScopePacked& scopeBefore) const {
+ set<TemporalNode> visitedNodes;
+ return isOrdered(TemporalNode{scopeAfter, TemporalOperator::SCOPE},
+ TemporalNode{scopeBefore, TemporalOperator::SCOPE},
+ visitedNodes);
+}
+
+bool
+TemporalSeqGraph::isOrdered(const TemporalNode& nodeAfter, const TemporalNode& nodeBefore, set<TemporalNode>& visitedNodes) const {
+ if (nodeAfter.scope == nodeBefore.scope && nodeAfter.mark == nodeBefore.mark) return true;
+ if (visitedNodes.count(nodeAfter)) return false;
+ visitedNodes.insert(nodeAfter);
+
+ auto frontierList = graph.right.equal_range(nodeAfter);
+ for(auto frontierIt = frontierList.first; frontierIt != frontierList.second; ++frontierIt) {
+ if(isOrdered(frontierIt->second, nodeBefore, visitedNodes)) return true;
+ }
+ return false;
+}
+
+namespace xreate {
+namespace cfa {
+ static string dictNodes[] = {"scope", "empty", "and", "or"};
+
+ std::ostream&
+ operator << (std::ostream& output, const TemporalNode& node) {
+ string op = dictNodes[node.mark];
+ output << op << "(" << node.scope << ")";
+
+ return output;
+ }
+}}
\ No newline at end of file
diff --git a/cpp/src/analysis/temporalseqgraph.h b/cpp/src/analysis/temporalseqgraph.h
new file mode 100644
index 0000000..c3672ec
--- /dev/null
+++ b/cpp/src/analysis/temporalseqgraph.h
@@ -0,0 +1,77 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * File: temporalseqgraph.h
+ * Author: pgess
+ *
+ * Created on February 4, 2019, 4:51 PM
+ */
+
+#ifndef TEMPORALSEQGRAPH_H
+#define TEMPORALSEQGRAPH_H
+
+#include "transcendlayer.h"
+
+namespace xreate{ namespace cfa{
+
+enum TemporalOperator {SCOPE, EMPTY, AND, OR};
+
+struct TemporalNode{
+ ScopePacked scope;
+ TemporalOperator mark;
+
+ friend std::ostream& operator << (std::ostream& output, const TemporalNode& node);
+ bool operator==(const TemporalNode& other) const
+ { return other.scope == scope && other.mark == mark; }
+};
+
+struct TemporalGuard{
+ enum{IN, OUT} mark;
+ unsigned int id;
+};
+
+typedef std::pair<TemporalNode, TemporalNode> Socket;
+
+}} namespace std {
+
+ bool operator<(const xreate::cfa::TemporalNode& x, const xreate::cfa::TemporalNode& y);
+
+} namespace xreate {namespace cfa {
+
+class TemporalSeqGraph: public IAnalysisReport{
+ typedef boost::bimap<
+ boost::bimaps::multiset_of<TemporalNode>,
+ boost::bimaps::multiset_of<TemporalNode>> Graph;
+
+public:
+ TemporalSeqGraph(TranscendLayer* transcend);
+
+ void addSubScopes(const CodeScope*, const std::list<CodeScope*>&);
+ void addBranchScopes(const CodeScope*, const std::list<CodeScope*>&);
+ Socket addSocket(const CodeScope*, TemporalOperator mark);
+ TemporalNode insertBefore(TemporalNode node, TemporalOperator mark);
+ TemporalNode insertAfter(TemporalNode node, TemporalOperator mark);
+ void connect(TemporalNode, TemporalNode);
+ void connectGuarded(const Socket& from, const Socket& to);
+ Socket getFnSocket(ManagedFnPtr calleeFn);
+ Socket getUncertainFnSocket(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates);
+
+ bool isOrdered(const ScopePacked& scopeAfter, const ScopePacked& scopeBefore) const;
+ bool isOrdered(const TemporalNode& nodeAfter, const TemporalNode& nodeBefore, std::set<TemporalNode>&) const;
+ void print(std::ostringstream &output) const override;
+
+private:
+ Graph graph;
+ std::multimap<TemporalNode, std::pair<TemporalNode, TemporalGuard>> graphGuarded;
+ ScopePacked __idNextVacant = 0;
+ unsigned int __guardNextVacant = 0;
+ TranscendLayer* __transcend;
+ std::map<ManagedFnPtr, Socket> __cacheFnSockets;
+ std::map<std::string, Socket> __cacheUncertainFnSockets;
+};
+}
+} //end of namespace xreate::cfa
+
+#endif /* TEMPORALSEQGRAPH_H */
+
diff --git a/cpp/src/aux/xreatemanager-decorators.cpp b/cpp/src/aux/xreatemanager-decorators.cpp
index 40bf519..07bd480 100644
--- a/cpp/src/aux/xreatemanager-decorators.cpp
+++ b/cpp/src/aux/xreatemanager-decorators.cpp
@@ -1,74 +1,75 @@
/* 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 "pass/interpretationpass.h"
#include "pass/versionspass.h"
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() {
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);
}
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/targets.h b/cpp/src/compilation/targets.h
index 0b31ddd..9a0b8cd 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,213 +1,223 @@
/* 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
#include "ast.h"
#include <boost/optional.hpp>
#include <map>
#include <list>
-namespace xreate{ namespace compilation {
-
-template <typename ConcreteTarget>
+namespace xreate{
+namespace compilation{
+
+template <typename ConcreteTarget>
struct TargetInfo{
- //typedef Result
- //typedef Function
- //typedef Scope
+ //typedef Result
+ //typedef Function
+ //typedef Scope
};
-
+
template<typename ConcreteTarget>
class Function;
template<typename ConcreteTarget>
class Target;
template<typename ConcreteTarget>
class Scope{
- typedef typename TargetInfo<ConcreteTarget>::Scope Self;
-
+ typedef typename TargetInfo<ConcreteTarget>::Scope Self;
+
public:
- const CodeScope* scope;
- Function<ConcreteTarget>* function=0;
-
- typename TargetInfo<ConcreteTarget>::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
- 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
- process(const Expression& expression)=0;
-
- Scope(const CodeScope* codeScope, Function<ConcreteTarget>* 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;
-
- 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){
- reset();
-
- for (auto entry: bindings){
- __bindings[entry.second] = entry.first;
- }
+ const CodeScope* scope;
+ Function<ConcreteTarget>* function = 0;
+
+ typename TargetInfo<ConcreteTarget>::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];
}
-
- bool
- isBindingDefined(const ScopedSymbol& id){
- return __bindings.count(id);
+
+ const Expression& declaration = CodeScope::getDefinition(s, true);
+ if(!declaration.isDefined()){
+ assert(false); //for bindings there should be result already
}
-
- void registerChildScope(std::shared_ptr<Self> scope){
- __childScopes.push_back(scope);
+
+ return self->__bindings[s.identifier] = self->process(declaration);
+ }
+
+ typename TargetInfo<ConcreteTarget>::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
+ process(const Expression& expression) = 0;
+
+ Scope(const CodeScope* codeScope, Function<ConcreteTarget>* 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;
+
+ 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));
}
- void reset(){
- __bindings.clear();
- __childScopes.clear();
+ overrideBindings(bindingsSymbols);
+ }
+
+ void
+ overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTarget>::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::list<std::shared_ptr<Self>> __childScopes;
+ std::map<ScopedSymbol, typename TargetInfo<ConcreteTarget>::Result> __bindings;
+ std::list<std::shared_ptr<Self>> __childScopes;
};
template<typename ConcreteTarget>
class Function{
- typedef typename TargetInfo<ConcreteTarget>::Result Result;
- typedef typename TargetInfo<ConcreteTarget>::Scope ConcreteScope;
-
+ typedef typename TargetInfo<ConcreteTarget>::Result Result;
+ typedef typename TargetInfo<ConcreteTarget>::Scope ConcreteScope;
+
public:
- Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
- : man(target), __function(function) {}
-
- virtual ~Function(){};
-
- 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();
+
+ Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
+ : man(target), __function(function){ }
+
+ virtual
+ ~Function(){ };
+
+ ConcreteScope*
+ getScope(const CodeScope * const scope){
+ if(__scopes.count(scope)){
+ auto result = __scopes.at(scope).lock();
+
+ if(result){
+ return result.get();
+ }
}
-
- virtual Result
- process(const std::vector<Result>& args)=0;
-
- Target<ConcreteTarget>* man=0;
- ManagedFnPtr __function;
+
+ 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;
protected:
- std::map<const CodeScope*, std::weak_ptr<ConcreteScope>> __scopes;
- std::shared_ptr<ConcreteScope> __entryScope;
+ 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;
-
- public:
- Target(AST* root): ast(root){}
-
- ConcreteFunction*
- getFunction(const ManagedFnPtr& function){
- unsigned int id = function.id();
-
- if (!__functions.count(id)){
- ConcreteFunction* unit = new ConcreteFunction(function, this);
- __functions.emplace(id, 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;
+class Target{
+ typedef typename TargetInfo<ConcreteTarget>::Function ConcreteFunction;
+
+public:
+
+ Target(AST* root): ast(root){ }
+
+ ConcreteFunction*
+ getFunction(const ManagedFnPtr& function){
+ unsigned int id = function.id();
+
+ if(!__functions.count(id)){
+ ConcreteFunction* unit = new ConcreteFunction(function, this);
+ __functions.emplace(id, 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/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 9c8648b..77e1f0b 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,206 +1,205 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
+
#include "ast.h"
#include "xreatemanager.h"
#include<iostream>
-namespace xreate
-{
- /** \brief Holds current position in %AST while traversing*/
- struct PassContext
- {
- const CodeScope* scope = 0;
- ManagedFnPtr function;
- ManagedRulePtr rule;
- std::string varDecl;
-
- PassContext()
- {}
-
- PassContext updateScope(const CodeScope* scopeNew) {
- PassContext context2{*this};
- context2.scope = scopeNew;
- return context2;
- }
-
- ~PassContext(){}
- };
-
- /** \brief Base class for all passes to inherit */
- class IPass {
- public:
- IPass(PassManager* manager);
- virtual ~IPass(){}
-
- /** \brief Executes pass */
- virtual void run()=0;
-
- /** \brief Finalizes pass. Empty by default*/
- virtual void finish();
-
- PassManager* man;
- };
-
- template<class Output>
- Output defaultValue();
-
- template<>
- void defaultValue<void>();
-
- /** \brief Stores processing results for already visited nodes */
- template<class Output>
- class SymbolCache: private std::map<Symbol, Output>{
- public:
- bool isCached(const Symbol& symbol){
- return this->count(symbol);
- }
-
- Output setCachedValue(const Symbol& symbol, Output&& value){
- (*this)[symbol] = value;
- return value;
- }
-
- Output getCachedValue(const Symbol& symbol){
- assert(this->count(symbol));
- return this->at(symbol);
- }
- };
-
- /** \brief Set of already visited nodes */
- template<>
- class SymbolCache<void>: private std::set<Symbol>{
- public:
- bool isCached(const Symbol& symbol){
- bool result = this->count(symbol) > 0;
- return result;
- }
- void setCachedValue(const Symbol& symbol){
- this->insert(symbol);
- }
-
- void getCachedValue(const Symbol& symbol){
- }
- };
-
-/** \brief Minimal useful IPass implementation*/
-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);
+namespace xreate {
+/** \brief Holds current position in %AST while traversing*/
+struct PassContext {
+ const CodeScope* scope = 0;
+ ManagedFnPtr function;
+ ManagedRulePtr rule;
+ std::string varDecl;
- const Expression& declaration = CodeScope::getDefinition(symbol, true);
- if (declaration.isDefined()){
- PassContext context2 = context.updateScope(symbol.scope);
+ PassContext() {}
- Output&& result = process(declaration, context2, hintSymbol);
- return __visitedSymbols.setCachedValue(symbol, std::move(result));
- }
+ PassContext updateScope(const CodeScope* scopeNew) {
+ PassContext context2{*this};
+ context2.scope = scopeNew;
+ return context2;
+ }
- return defaultValue<Output>();
- }
+ ~PassContext() {}
+};
- Output processExpressionCall(const Expression& expression, PassContext context){
- const std::string &calleeName = expression.getValueString();
- std::list<ManagedFnPtr> callees = man->root->getFunctionSpecializations(calleeName);
- if (callees.size() == 1 && callees.front()){
- return processFnCall(callees.front(), context);
+/** \brief Base class for all passes to inherit */
+class IPass {
+public:
+ IPass(PassManager* manager);
- } else {
- for (const ManagedFnPtr& callee: callees){
- processFnCallUncertain(callee, context);
- }
+ virtual ~IPass() {}
- return defaultValue<Output>();
- }
- }
+ /** \brief Executes pass */
+ virtual void run() = 0;
- SymbolCache<Output>& getSymbolCache(){
- return __visitedSymbols;
- }
+ /** \brief Finalizes pass. Empty by default*/
+ virtual void finish();
+
+ PassManager* man;
+};
+
+template<class Output>
+Output
+defaultValue();
+
+template<>
+void
+defaultValue<void>();
+
+/** \brief Stores processing results for already visited nodes */
+template<class Output>
+class SymbolCache : private std::map<Symbol, Output> {
+public:
+ bool isCached(const Symbol &symbol) {
+ return this->count(symbol);
+ }
+
+ Output setCachedValue(const Symbol &symbol, Output &&value) {
+ (*this)[symbol] = value;
+ return value;
+ }
+
+ Output getCachedValue(const Symbol &symbol) {
+ assert(this->count(symbol));
+ return this->at(symbol);
+ }
+};
+/** \brief Set of already visited nodes */
+template<>
+class SymbolCache<void> : private std::set<Symbol> {
public:
- AbstractPass(PassManager* manager)
- : IPass(manager){}
+ bool isCached(const Symbol &symbol) {
+ bool result = this->count(symbol) > 0;
+ return result;
+ }
- /** \brief Processes function invocation instruction */
- virtual Output processFnCall(ManagedFnPtr functionCallee, PassContext context){
- return defaultValue<Output>();
- }
+ void setCachedValue(const Symbol &symbol) {
+ this->insert(symbol);
+ }
+
+ void getCachedValue(const Symbol &symbol) {
+ }
+};
+
+/** \brief Minimal useful IPass implementation*/
+template<class Output>
+class AbstractPass : public IPass {
+ SymbolCache<Output> __visitedSymbols;
- /** \brief Processes function invocation instruction in uncertain cases
- * \details Executed when it's impossible statically determine exact function invocation.
- * In this case get executed for all possible candidates
- */
- virtual void processFnCallUncertain(ManagedFnPtr functionCallee, PassContext context)
- {}
+protected:
+ virtual Output processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol = "") {
+ if(__visitedSymbols.isCached(symbol))
+ return __visitedSymbols.getCachedValue(symbol);
- /** \brief Processes Logic Rule */
- virtual void process(ManagedRulePtr rule)
- {}
+ const Expression &declaration = CodeScope::getDefinition(symbol, true);
+ if(declaration.isDefined()) {
+ PassContext context2 = context.updateScope(symbol.scope);
- /** \brief Processes Function */
- virtual Output process(ManagedFnPtr function)
- {
- PassContext context;
- context.function = function;
+ Output &&result = process(declaration, context2, hintSymbol);
+ return __visitedSymbols.setCachedValue(symbol, std::move(result));
+ }
- return process(function->getEntryScope(), context);
- }
+ return defaultValue<Output>();
+ }
- /** \brief Processes single CodeScope */
- virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
- context.scope = scope;
+ Output processExpressionCall(const Expression &expression, PassContext context) {
+ const std::string &calleeName = expression.getValueString();
+ std::list<ManagedFnPtr> callees = man->root->getFunctionSpecializations(calleeName);
- return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
+ //Determined specialization
+ if(callees.size() == 1 && callees.front()) {
+ return processFnCall(callees.front(), 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>();
+ //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;
}
- /** \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;
- }
+ 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);
+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);
+AbstractPass<void>::process(const Expression &expression, PassContext context, const std::string &hintSymbol);
-}
+}
#endif
diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp
index 2a51dc4..3756331 100644
--- a/cpp/src/pass/cfapass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,198 +1,124 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* cfapass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file cfapass.h
* \brief Control Flow Analysis(CFA)
*/
-#include "cfapass.h"
+#include "pass/cfapass.h"
#include "analysis/cfagraph.h"
-#include "analysis/DominatorsAnalysisProvider.h"
-
#include <boost/range/iterator_range_core.hpp>
using namespace std;
-using namespace xreate::cfa;
-void
-CFAPassBasic::initSignatures(){
- auto range = man->root->__interfacesData.equal_range(CFA);
- for (auto i = range.first; i!= range.second; ++i){
- __signatures.emplace(i->second.op, i->second);
- }
-}
+namespace xreate {
+namespace cfa {
void
-CFAPassBasic::run(){
- initSignatures();
-
- return AbstractPass::run();
+CFAPass::initSignatures() {
+ auto range = man->root->__interfacesData.equal_range(CFA);
+ for(auto i = range.first; i != range.second; ++i) {
+ __signatures.emplace(i->second.op, i->second);
+ }
}
void
-CFAPassBasic::finish(){
- man->transcend->registerReport(__context.graph);
- boost::scoped_ptr<dominators::CFAGraphAdapter> cfaAdapter(dominators::CFAGraphAdapter::build(__context.graph));
- dominators::DominatorsAnalysisProvider* reportDominators = new dominators::DominatorsAnalysisProvider();
- reportDominators->run(cfaAdapter.get());
- man->transcend->registerReport(reportDominators);
-
- return AbstractPass::finish();
+CFAPass::run() {
+ initSignatures();
+
+ return AbstractPass::run();
}
void
-CFAPassBasic::processFnCall(ManagedFnPtr function, PassContext context){
- TranscendLayer* transcend = man->transcend;
- __context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
+CFAPass::finish() {
+ man->transcend->registerReport(__context.graph);
- return AbstractPass::processFnCall(function, context);
+ return AbstractPass::finish();
}
void
-CFAPassBasic::processFnCallUncertain(ManagedFnPtr function, PassContext context){
- TranscendLayer* transcend = man->transcend;
- __context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
+CFAPass::processFnCall(ManagedFnPtr function, PassContext context) {
+ TranscendLayer* transcend = man->transcend;
+ __context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
- return AbstractPass::processFnCallUncertain(function, context);
+ return AbstractPass::processFnCall(function, context);
}
void
-CFAPassBasic::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
- TranscendLayer* transcend = man->transcend;
-
- const CodeScope* scopeParent = context.scope;
- ScopePacked scopeId = transcend->pack(scope);
-
- __context.graph->addScope(scope);
-
- //Parent Relations
- if (scopeParent){
- __context.graph->addParentConnection(scopeId, transcend->pack(scopeParent));
- } else {
- __context.graph->addParentConnection(scopeId, context.function->getName());
- }
+CFAPass::processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
+ TranscendLayer* transcend = man->transcend;
+ __context.graph->addCallConnection(transcend->pack(context.scope), calleeName);
- //TOTEST scope annotations
- //SECTIONTAG context gather scope annotations
- __context.graph->addScopeAnnotations(scopeId, scope->tags);
-
- __context.graph->addContextRules(scopeId, scope->contextRules);
-
- return AbstractPass::process(scope, context, hintBlockDecl);
+ return AbstractPass::processFnCallUncertain(calleeName, candidates, context);
}
-//TOTEST scope annotations via scheme
void
-CFAPassBasic::process(const Expression& expression, PassContext context, const std::string& varDecl){
- TranscendLayer* transcend = man->transcend;
+CFAPass::process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl) {
+ TranscendLayer* transcend = man->transcend;
- if (expression.__state == Expression::COMPOUND){
- Operator op= expression.op;
+ const CodeScope* scopeParent = context.scope;
+ ScopePacked scopeId = transcend->pack(scope);
- if (__signatures.count(op)) {
- assert(expression.blocks.size());
+ __context.graph->addScope(scope);
- for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
- __context.graph->addScopeAnnotations(transcend->pack(expression.blocks.front()), scheme.second.getOperands());
- }
- }
- }
+ //Parent Relations
+ if(scopeParent) {
+ __context.graph->addParentConnection(scopeId, transcend->pack(scopeParent));
+ } else {
+ __context.graph->addParentConnection(scopeId, context.function->getName());
+ }
- return AbstractPass::process(expression, context, varDecl);
-}
+ //TOTEST scope annotations
+ //SECTIONTAG context gather scope annotations
+ __context.graph->addScopeAnnotations(scopeId, scope->tags);
-void
-CFAPassBasic::process(ManagedFnPtr function){
- __context.graph->addFunctionAnnotations(function->getName(), function->getTags());
- return AbstractPass::process(function);
+ __context.graph->addContextRules(scopeId, scope->contextRules);
+
+ return AbstractPass::process(scope, context, hintBlockDecl);
}
-CFAPassBasic::CFAPassBasic(PassManager* manager)
-: AbstractPass(manager)
- , __context{new CFAGraph(manager->transcend)}
-{}
+//TOTEST scope annotations via scheme
-/****************************SCOPE DEPENDENCIES********************************/
void
-CFAPassDependenciesDecorator::process(const Expression& expression, PassContext context, const std::string& varDecl){
- TranscendLayer* transcend = man->transcend;
-
- if (expression.__state == Expression::COMPOUND)
- switch(expression.op){
- case Operator::SEQUENCE:{
- ScopePacked scopePrev = transcend->pack(expression.blocks.front());
- for(auto scopeIt= ++expression.blocks.begin(); scopeIt != expression.blocks.end(); ++scopeIt){
- ScopePacked scopeCurrent = transcend->pack(*scopeIt);
- __context.graph->addDependency(scopeCurrent, scopePrev);
- scopePrev = scopeCurrent;
- }
- break;
- }
-
- default: break;
- }
+CFAPass::process(const Expression &expression, PassContext context, const std::string &varDecl) {
+ TranscendLayer* transcend = man->transcend;
- return Parent::process(expression, context, varDecl);
-}
+ if(expression.__state == Expression::COMPOUND) {
+ Operator op = expression.op;
-void
-CFAPassDependenciesDecorator::processFnCall(ManagedFnPtr function, PassContext context){
- TranscendLayer* transcend = man->transcend;
+ if(__signatures.count(op)) {
+ assert(expression.blocks.size());
- const CodeScope* scopeCaller = context.scope;
- assert(scopeCaller);
- ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
-
- if(__context.graph->isDependent(scopeCallerPacked)){
- ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
- __context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
+ for(const auto &scheme : boost::make_iterator_range(__signatures.equal_range(expression.op))) {
+ __context.graph->addScopeAnnotations(transcend->pack(expression.blocks.front()), scheme.second.getOperands());
+ }
}
+ }
- Parent::processFnCall(function, context);
+ return AbstractPass::process(expression, context, varDecl);
}
void
-CFAPassDependenciesDecorator::processFnCallUncertain(ManagedFnPtr function, PassContext context){
- TranscendLayer* transcend = man->transcend;
-
- const CodeScope* scopeCaller = context.scope;
- assert(scopeCaller);
- ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
-
- if(__context.graph->isDependent(scopeCallerPacked)){
- ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
- __context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
- }
-
- Parent::processFnCallUncertain(function, context);
+CFAPass::process(ManagedFnPtr function) {
+ __context.graph->addFunctionAnnotations(function->getName(), function->getTags());
+ return AbstractPass::process(function);
}
-void
-CFAPassDependenciesDecorator::process(CodeScope* scope,
- PassContext context, const std::string& hintBlockDecl){
-
- TranscendLayer* transcend = man->transcend;
- const CodeScope* scopeParent = context.scope;
-
- if (scopeParent){
- ScopePacked scopePacked = transcend->pack(scope);
- ScopePacked scopeParentPacked = transcend->pack(scopeParent);
- if (!__context.graph->isDependent(scopePacked) &&
- __context.graph->isDependent(scopeParentPacked)) {
- __context.graph->transmitDependencies(scopePacked, scopeParentPacked);
- }
- }
+CFAPass::CFAPass(PassManager* manager)
+: AbstractPass(manager), __context{new CFAGraph(manager->transcend)}
+{
+}
- Parent::process(scope, context, hintBlockDecl);
+}
}
/**
* \class xreate::cfa::CFAPass
* \details Provides CFA, important analysis for reasoning. Iterates over AST and stores collected data in CFAGraph
*/
diff --git a/cpp/src/pass/cfapass.h b/cpp/src/pass/cfapass.h
index 20f7467..b4ee3c8 100644
--- a/cpp/src/pass/cfapass.h
+++ b/cpp/src/pass/cfapass.h
@@ -1,67 +1,51 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* cfapass.cpp
* Control Flow Graph building pass
*/
#ifndef CFGPASS_H
#define CFGPASS_H
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "abstractpass.h"
+#include "analysis/cfagraph.h"
namespace xreate{namespace cfa {
class CFAGraph;
/** \brief Control Flow Analysis Pass(%CFA)*/
-class CFAPassBasic : public AbstractPass<void>{
+class CFAPass : public AbstractPass<void>{
public:
void process(ManagedFnPtr function) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
- void processFnCallUncertain(ManagedFnPtr function, PassContext context) override;
+ void processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) override;
void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
- CFAPassBasic(PassManager* manager);
+ CFAPass(PassManager* manager);
void finish() override;
void run() override;
const CFAGraph* getReport() const {return __context.graph; }
protected:
struct {
CFAGraph* graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
};
-class CFAPassDependenciesDecorator: public CFAPassBasic{
- typedef CFAPassBasic Parent;
-
-public:
- CFAPassDependenciesDecorator(PassManager* manager): CFAPassBasic(manager) {}
-
- void process(const Expression& expression, PassContext context, const std::string& varDecl) override;
- void processFnCall(ManagedFnPtr function, PassContext context) override;
- void processFnCallUncertain(ManagedFnPtr function, PassContext context) override;
- void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) override;
-};
-
-class CFAPass: public CFAPassDependenciesDecorator{
-public:
- CFAPass(PassManager* manager): CFAPassDependenciesDecorator(manager) {}
-};
-
}} //end of namespace xreate::cfa
#endif // CFGPASS_H
diff --git a/cpp/src/pass/cfatemporalseqpass.cpp b/cpp/src/pass/cfatemporalseqpass.cpp
new file mode 100644
index 0000000..9710e61
--- /dev/null
+++ b/cpp/src/pass/cfatemporalseqpass.cpp
@@ -0,0 +1,125 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * File: cfatemporalseqpass.cpp
+ * Author: pgess
+ *
+ * Created on February 4, 2019, 4:43 PM
+ */
+
+/**
+ * \file cfatemporalseqpass.h
+ * \brief Context Blocks' compilation order analysis.
+ */
+
+#include "pass/cfatemporalseqpass.h"
+#include "analysis/temporalseqgraph.h"
+
+using namespace xreate::cfa;
+using namespace std;
+
+namespace xreate {
+ template<>
+ cfa::Socket defaultValue<cfa::Socket>() {
+ const cfa::TemporalNode invalidNode{(ScopePacked) - 1, cfa::TemporalOperator::EMPTY};
+ return make_pair(invalidNode, invalidNode);
+ };
+}
+
+CFATemporalSeqPass::CFATemporalSeqPass(PassManager* manager)
+: AbstractPass(manager), __graph(new TemporalSeqGraph(manager->transcend)) { }
+
+void
+CFATemporalSeqPass::finish() {
+ man->transcend->registerReport(__graph);
+ return AbstractPass::finish();
+}
+
+void
+CFATemporalSeqPass::process(
+ const Expression &expression,
+ PassContext context,
+ const std::string &varDecl) {
+
+ TranscendLayer* transcend = man->transcend;
+
+ if(expression.__state == Expression::COMPOUND) {
+ Operator op = expression.op;
+
+ switch(op) {
+ case Operator::QUERY_LATE:
+ case Operator::MAP:
+ case Operator::FOLD:
+ case Operator::INF:
+ {
+ __graph->addSubScopes(context.scope,
+ expression.blocks);
+ break;
+ }
+
+ case Operator::IF:
+ case Operator::SWITCH:
+ case Operator::SWITCH_LATE:
+ case Operator::SWITCH_VARIANT:
+ {
+ __graph->addBranchScopes(context.scope,
+ expression.blocks);
+ break;
+ }
+
+ case Operator::SEQUENCE:
+ {
+ auto socket = __graph->addSocket(context.scope, TemporalOperator::AND);
+ auto nodeFrom = socket.first;
+
+ for(auto scopeIt = expression.blocks.begin(); scopeIt != expression.blocks.end(); ++scopeIt) {
+ ScopePacked scope = transcend->pack(*scopeIt);
+ TemporalNode node{scope, TemporalOperator::SCOPE};
+
+ __graph->connect(nodeFrom, node);
+ nodeFrom = node;
+ }
+
+ __graph->connect(nodeFrom, socket.second);
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return Parent::process(expression, context, varDecl);
+}
+
+void
+CFATemporalSeqPass::processFnCall(ManagedFnPtr functionCallee, PassContext context) {
+ auto callerSock = __graph->addSocket(context.scope, TemporalOperator::AND);
+ auto calleeSock = __graph->getFnSocket(functionCallee);
+
+ __graph->connectGuarded(callerSock, calleeSock);
+}
+
+void
+CFATemporalSeqPass::processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
+ auto callerSock = __graph->addSocket(context.scope, TemporalOperator::AND);
+ auto calleeSock = __graph->getUncertainFnSocket(calleeName, candidates);
+
+ __graph->connectGuarded(callerSock, calleeSock);
+}
+
+void
+CFATemporalSeqPass::process(ManagedFnPtr function) {
+ TranscendLayer* transcend = man->transcend;
+
+ Socket fnSocket = __graph->getFnSocket(function);
+ TemporalNode entryNode{
+ transcend->pack(function->getEntryScope()),
+ TemporalOperator::SCOPE
+ };
+
+ __graph->connect(fnSocket.first, entryNode);
+ __graph->connect(entryNode, fnSocket.second);
+
+ return Parent::process(function);
+}
\ No newline at end of file
diff --git a/cpp/src/pass/cfatemporalseqpass.h b/cpp/src/pass/cfatemporalseqpass.h
new file mode 100644
index 0000000..c5d15e6
--- /dev/null
+++ b/cpp/src/pass/cfatemporalseqpass.h
@@ -0,0 +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: cfatemporalseqpass.h
+ * Author: pgess
+ *
+ * Created on February 4, 2019, 4:43 PM
+ */
+
+#ifndef CFATEMPORALSEQPASS_H
+#define CFATEMPORALSEQPASS_H
+
+#include "xreatemanager.h"
+#include "abstractpass.h"
+
+namespace xreate{namespace cfa {
+
+class TemporalSeqGraph;
+
+class CFATemporalSeqPass: public AbstractPass<void>{
+ typedef AbstractPass<void> Parent;
+
+public:
+ CFATemporalSeqPass(PassManager* manager);
+ void processFnCall(ManagedFnPtr functionCallee, PassContext context) override;
+ void processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) override;
+ void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
+ void process(ManagedFnPtr function) override;
+
+ const TemporalSeqGraph* getReport() const {return __graph; }
+ void finish() override;
+
+private:
+ TemporalSeqGraph* __graph;
+};
+
+}} //end of namespace xreate::cfa
+
+#endif /* CFATEMPORALSEQPASS_H */
+
diff --git a/cpp/src/transcendlayer.cpp b/cpp/src/transcendlayer.cpp
index 26ced04..adfda07 100644
--- a/cpp/src/transcendlayer.cpp
+++ b/cpp/src/transcendlayer.cpp
@@ -1,496 +1,501 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: transcendlayer.cpp
*/
/**
* \file transcendlayer.h
* \brief Reasoner. Wrapper over the external Clasp reasoner library
*/
#include "transcendlayer.h"
#include "analysis/utils.h"
#include "utils.h"
#include <gringo/scripts.hh>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <memory>
#include <boost/variant/detail/apply_visitor_binary.hpp>
using namespace std;
//TODO escape identifiers started with upper case symbol
namespace xreate{
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2) {
return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
}
struct VisitorSymbolNodeHash : public boost::static_visitor<size_t>{
std::size_t operator()(const xreate::SymbolPacked& node) const noexcept {
return 2 * (node.identifier + 3 * node.scope + 5 * std::abs(node.version));
}
std::size_t operator()(const xreate::SymbolAnonymous& node) const noexcept {
return 7 * node.id;
}
} ;
}
namespace std{
std::size_t
hash<xreate::SymbolNode>::operator()(xreate::SymbolNode const& s) const noexcept {
return boost::apply_visitor(xreate::VisitorSymbolNodeHash(), s);
}
std::size_t
hash<xreate::SymbolGeneralized>::operator()(xreate::SymbolGeneralized const& s) const noexcept {
return xreate::AttachmentsId<xreate::SymbolGeneralized>::getId(s);
}
}
namespace xreate{
void
TranscendLayer::printWarnings(std::ostream& out) {
const std::string warningTag = "warning";
auto warningsModel = query(warningTag);
if(warningsModel.size())
for(auto warning : warningsModel) {
unsigned int warningId;
Gringo::Symbol params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning.second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out << params;
}
}
bool
TranscendLayer::processSolution(Gringo::Model const &model) {
cout << "Model: " << endl;
const string& atomBindVar = Config::get("transcend.bindings.variable");
const string& atomBindFunc = Config::get("transcend.bindings.function");
const string& atomBindScope = Config::get("transcend.bindings.scope");
for(Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
atom.print(cout);
cout << " | " << endl;
string atomName(atom.name().c_str());
if(atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope) {
string atomAlias = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.emplace(atomAlias, atom);
continue;
}
__model.emplace(atomName, atom);
}
return true;
}
void
TranscendLayer::registerReport(IAnalysisReport * report) {
__reports.push_back(report);
}
void
-TranscendLayer::runReports() {
+TranscendLayer::printReports() {
for(IAnalysisReport* report : __reports) {
report->print(__partGeneral);
- delete report;
}
+}
- __reports.clear();
+void
+TranscendLayer::deleteReports(){
+ for(IAnalysisReport* report : __reports) {
+ delete report;
+ }
+ __reports.clear();
}
void
TranscendLayer::addRuleWarning(const RuleWarning & rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch(argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list < string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression & guard) {
return xreate::analysis::compile(guard);
});
const list<string>& guards = xreate::analysis::multiplyLists(std::move(guardsRaw));
list<string> &&branches = xreate::analysis::compileNeg(rule.__condition);
boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
for(const string &guardsJoined : guards)
for(const string &branch : branches) {
unsigned int hook = registerWarning(string(rule.__message));
__partGeneral << formatWarning
% (hook)
% (boost::algorithm::join(vars, ", "))
% (branch)
% (guardsJoined)
% (boost::algorithm::join(domains, ", "))
<< endl;
}
}
unsigned int
TranscendLayer::registerWarning(std::string && message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;
}
void
TranscendLayer::involveImports() {
ostream &out = __partGeneral;
if(ast)
for(string fn : ast->__rawImports) {
std::ifstream file(fn);
if(!file) {
std::cout << "Can't process script file: " << fn << std::endl;
assert(false);
}
while(!file.eof()) {
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
TranscendLayer::addRawScript(std::string && script) {
__partGeneral << script;
}
void
TranscendLayer::run() {
involveImports();
- runReports();
+ printReports();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), { }, 0);
ctl.add("base",{}, program.str());
ctl.ground({
{"base",
{}}
}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
this->processSolution(model);
return true;
},
{
});
if(result.satisfiable() == Gringo::SolveResult::Satisfiable) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process solution
for(auto q : __queries) {
q.second->init(this);
}
}
TranscendLayer::TranscendLayer() : ast(nullptr) { }
StaticModel
TranscendLayer::query(const std::string & atom) const {
StaticModel result;
if (! __model.count(atom)) {
return result;
}
auto currentDataRange = __model.equal_range(atom);
std::copy(currentDataRange.first, currentDataRange.second, std::inserter(result, result.end()));
return result;
}
ScopePacked
TranscendLayer::pack(const CodeScope * const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if(pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
size_t
TranscendLayer::getScopesCount() const {
return __registryScopes.size();
}
SymbolPacked
TranscendLayer::pack(const Symbol& symbol, std::string hintSymbolName) {
SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
TranscendLayer::unpack(const SymbolPacked & symbol) const {
return Symbol{ScopedSymbol
{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]};
};
std::string
TranscendLayer::getHintForPackedSymbol(const SymbolPacked & symbol) {
auto result = __indexSymbolNameHints.find(symbol);
return(result == __indexSymbolNameHints.end()) ? "" : result->second;
}
IQuery *
TranscendLayer::registerQuery(IQuery *query, const QueryId & id) {
return __queries.emplace(id, query).first->second;
}
IQuery *
TranscendLayer::getQuery(const QueryId & id) {
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
class VisitorUnpackSymbol : public boost::static_visitor<SymbolGeneralized>{
public:
VisitorUnpackSymbol(const TranscendLayer* transcend) : __transcend(transcend) { }
SymbolGeneralized operator()(const SymbolPacked& symbol) const {
return __transcend->unpack(symbol);
}
SymbolGeneralized operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
const TranscendLayer* __transcend;
} ;
class VisitorPackSymbol : public boost::static_visitor<SymbolNode>{
public:
VisitorPackSymbol(TranscendLayer* transcend, const std::string& hintSymbolName)
: __transcend(transcend), __hint(hintSymbolName) { }
SymbolNode operator()(const Symbol& symbol) const {
return __transcend->pack(symbol, __hint);
}
SymbolNode operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
TranscendLayer* __transcend;
std::string __hint;
} ;
SymbolNode
TranscendLayer::pack(const SymbolGeneralized& symbol, const std::string & hintSymbolName) {
return boost::apply_visitor(VisitorPackSymbol(this, hintSymbolName), symbol);
}
SymbolGeneralized
TranscendLayer::unpack(const SymbolNode & symbol) const {
return boost::apply_visitor(VisitorUnpackSymbol(this), symbol);
}
bool
operator==(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool
operator<(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
Expression
ParseImplAtom<Expression>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Num: return Expression(atom.num());
case Gringo::SymbolType::Str: return Expression(Atom<String_t>(std::string(atom.string().c_str())));
case Gringo::SymbolType::Fun:
{
//FUNC
Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name().c_str())))});
for(const Gringo::Symbol& arg : atom.args()) {
result.addArg(ParseImplAtom<Expression>::get(arg));
}
return result;
}
default:
{
assert(false);
}
}
}
int
ParseImplAtom<int>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Num: return atom.num();
default: break;
}
assert(false && "Inappropriate symbol type");
}
std::string
ParseImplAtom<std::string>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Str: return atom.string().c_str();
case Gringo::SymbolType::Fun: return atom.name().c_str();
default: break;
}
assert(false && "Inappropriate symbol type");
}
SymbolPacked
ParseImplAtom<SymbolPacked>
::get(const Gringo::Symbol & atom) {
auto result = TranscendLayer::parse<int, int, int>(atom);
return SymbolPacked(std::get<0>(result), std::get<1>(result), std::get<2>(result));
};
Gringo::Symbol
ParseImplAtom<Gringo::Symbol>
::get(const Gringo::Symbol & atom) {
return atom;
}
SymbolNode
ParseImplAtom<SymbolNode>
::get(const Gringo::Symbol & atom) {
assert(atom.type() == Gringo::SymbolType::Fun
&& "Inappropriate symbol type");
if(atom.name() == "a") {
return SymbolAnonymous{(unsigned int) std::get<0>(TranscendLayer::parse<int>(atom))};
} else if(atom.name() == "s") {
return ParseImplAtom<SymbolPacked>::get(atom);
}
assert(false && "Wrong symbol format");
}
class VisitorSymbolId : public boost::static_visitor<unsigned int>{
public:
unsigned int operator()(const Symbol& symbol) const {
return AttachmentsId<Symbol>::getId(symbol);
}
unsigned int operator()(const SymbolAnonymous& symbol) const {
return symbol.id;
}
} ;
unsigned int
AttachmentsId<SymbolGeneralized>
::getId(const SymbolGeneralized & symbol) {
return boost::apply_visitor(VisitorSymbolId(), symbol);
}
} //end of xreate namespace
/**
* \class xreate::TranscendLayer
* \brief Reasoning and logic Solver.
*
* Wraps external brilliant fantastic tool [Clasp solver](https://potassco.org/clasp/)
*
* For building *logic program* for reasoning TranscendLayer takes input from:
* - Raw scripts. Client could append arbitrary ASP script to _logic program_. \ref addRawScript()
* - Includes. There is possibility to specify external files with ASP scripts
* to append to _logic program_. \ref involveImports() (private member)
* - Diagnostic rules. Rules that produce diagnostic messages during
* compilation(warnings) or even able to halt compilation with errors.
* addRuleWarning(), \ref registerWarning()
* - DFA data. \ref setDFAData()
* - CFA data. \ref setCFAData()
* - Dominators Analysis. See xreate::dominators::DominatorsAnalysisProvider.
* Executed by \ref run()
* - Context rules. See xreate::ContextRule and general [Context Explanation](/w/concepts/context)
*
* Data sources implement xreate::IAnalysisReport. Generally, input could be loosely divided into three categories:
* - *Internally derived* data. CFA, DFA, Dominators analyses *automatically* feed reasoner by
* useful insights about data, structure and algorithms of a program
* - *User provided* data. CFA, DFA, Diagnostic/Context rules feed reasoner by
* annotations Developer specifically provides manually
* - *External* data. Raw scripts and includes feed reasoner with third-party data
* related to a different aspects of a program possibly produced by external analyzers
*
* Once TranscendLayer got input from all providers and logic program is fully constructed
* it runs external Clasp reasoner and receives back desired solutions.
*
* Output of the external Clasp reasoner is recognized and accessed via *queries*.
* IQuery represents an interface between reasoner's output and rest of Xreate.
* Each query inherits xreate::IQuery interface. Currently there are queries as follows:
* - xreate::containers::Query to catch solutions regarding Containers implementation. See [Containers Explanation](/w/concepts/containers)
* - xreate::context::ContextQuery to catch solution regarding Context. See [Context Explanation](/w/concepts/context)
*
* \sa See xreate::dfa::DFAPass, xreate::cfa::CFAPass, xreate::IQuery, xreate::IAnalysisReport, xreate::dominators::DominatorsAnalysisProvider
*/
diff --git a/cpp/src/transcendlayer.h b/cpp/src/transcendlayer.h
index e657c1c..e0051bb 100644
--- a/cpp/src/transcendlayer.h
+++ b/cpp/src/transcendlayer.h
@@ -1,283 +1,284 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: transcendlayer.h
*/
#ifndef transcendLAYER_H
#define transcendLAYER_H
#include "ast.h"
#include "contextrule.h"
#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <list>
#include <limits>
namespace xreate {
typedef unsigned int ScopePacked;
const ScopePacked SCOPE_ABSTRACT_GLOBAL = std::numeric_limits<ScopePacked>::max();
struct SymbolPacked {
SymbolPacked(){}
SymbolPacked(ScopedSymbol i, ScopePacked s): identifier(i.id), version(i.version), scope(s){}
SymbolPacked(VNameId symbolId, versions::VariableVersion symbolVersion, ScopePacked symbolScope)
: identifier(symbolId), version(symbolVersion), scope(symbolScope){}
VNameId identifier;
versions::VariableVersion version;
ScopePacked scope;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
struct SymbolAnonymous {
unsigned int id;
bool flagIsUsed = false;
};
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2);
typedef boost::variant<SymbolAnonymous, SymbolPacked> SymbolNode;
//DEBT use SymbolGeneralized communicating with Analysis rather than Symbol
typedef boost::variant<SymbolAnonymous, Symbol> SymbolGeneralized;
template<>
struct AttachmentsId<SymbolGeneralized>{
static unsigned int getId(const SymbolGeneralized& symbol);
};
} namespace std {
template<>
struct hash<xreate::SymbolNode> {
std::size_t operator()(xreate::SymbolNode const& s) const noexcept;
};
template<>
struct hash<xreate::SymbolGeneralized> {
std::size_t operator()(xreate::SymbolGeneralized const& s) const noexcept;
};
}
namespace xreate {
enum class DFGConnection {
STRONG, WEAK, PROTOTYPE
};
/** \brief Designated to mark analysis results that can be composed as *logic program* */
class IAnalysisReport {
public:
/** \brief Composes *logic program* based on analysis data into ASP format and appends to a stream*/
virtual void print(std::ostringstream& output) const = 0;
virtual ~IAnalysisReport(){};
};
/** \brief Logic program query interface */
class IQuery {
public:
virtual void init(TranscendLayer* transcend) = 0;
virtual ~IQuery() {}
};
enum class QueryId {
ContainersQuery,
PolymorphQuery,
LatexQuery
};
namespace dfa{
class DFAGraph;
}
namespace cfa {
class CFAGraph;
}
typedef std::multimap<std::string, Gringo::Symbol> StaticModel;
typedef StaticModel::const_iterator StaticModelIterator;
class TranscendLayer {
friend class ContextRule;
/**\name Data Providers Management */
///@{
public:
void registerReport(IAnalysisReport* report);
- void runReports();
+ void printReports();
+ void deleteReports();
/** \brief Appends arbitrary string to *logic program*
*/
void addRawScript(std::string&& script);
private:
std::list<IAnalysisReport*> __reports;
/** Includes external text files to a *logic program* */
void involveImports();
///@}
/**\name Queries Management */
///@{
public:
/** \brief Adds query. See xreate::IQuery */
IQuery* registerQuery(IQuery* query, const QueryId& id);
/** \brief Returns particular query. See xreate::IQuery */
IQuery* getQuery(const QueryId& id);
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Symbol& atom);
StaticModel query(const std::string& atom) const;
size_t getScopesCount() const;
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
ScopePacked pack(const CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol) const;
SymbolNode pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName);
SymbolGeneralized unpack(const SymbolNode& symbol) const;
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
///@}
private:
std::map<QueryId, IQuery*> __queries;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<const CodeScope*> __registryScopes;
/**\name Diagnostic */
///@{
//TODO diagnostic move over to separate provider/query
public:
/** \brief Adds diagnostic rule */
void addRuleWarning(const RuleWarning &rule);
/** \brief Registers diagnostic messages */
unsigned int registerWarning(std::string &&message);
private:
std::map<unsigned int, std::string> __warnings;
void printWarnings(std::ostream& out);
///@}
///@{
public:
TranscendLayer();
/** \brief Executes reasoning */
void run();
///@}
AST *ast;
protected:
virtual bool processSolution(Gringo::Model const &model);
private:
StaticModel __model;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<int> {
static int get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolNode> {
static SymbolNode get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<Gringo::Symbol> {
static Gringo::Symbol get(const Gringo::Symbol& atom);
};
template<class ItemType>
struct ParseImplAtom<std::list<ItemType>>{
static std::list<ItemType>
get(const Gringo::Symbol& atom){
bool flagIsList = (atom.type() == Gringo::SymbolType::Fun) && atom.name().empty();
std::list<ItemType> result;
if(!flagIsList) {
//treat as degenerate case: list with a single element
result.push_back(ParseImplAtom<ItemType>::get(atom));
return result;
}
for (const Gringo::Symbol& arg: atom.args()) {
result.push_back(ParseImplAtom<ItemType>::get(arg));
}
return result;
}
};
template<>
struct ParseImplAtom<Expression> {
static Expression get(const Gringo::Symbol& atom);
};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType;
ElType& el = std::get < tupleSize - index > (tup);
Gringo::Symbol atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index - 1 > ::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0> {
static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
}
};
template<class ...Types>
std::tuple<Types...>
TranscendLayer::parse(const Gringo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
} //end of xreate namespace
#endif
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index b45173b..626ec4a 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,167 +1,172 @@
/* 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"
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.h b/cpp/src/xreatemanager.h
index 5609a31..19919de 100644
--- a/cpp/src/xreatemanager.h
+++ b/cpp/src/xreatemanager.h
@@ -1,141 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.h
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
/**
* \file
* \brief Entry point of Xreate API.
*
*/
#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,
+ CFAPass, CFATemporalSeqPass,
CompilePass,
DFAPass,
EnvironmentTestsPass,
LoggerPass,
RulesPass,
InterpretationPass,
VersionsPass
};
/**
* \class PassManager
* \brief 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:
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
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 ee87e1a..a178bcc 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,57 +1,58 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate-tests)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES($<TARGET_PROPERTY:xreate,INCLUDE_DIRECTORIES>)
# TESTS
#=========================
FIND_PACKAGE (LLVM REQUIRED)
message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
#aux_source_directory(. TEST_FILES)
set(TEST_FILES
+ 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/xml2.cpp
#vendorsAPI/json.cpp
containers.cpp
interpretation.cpp
loops.cpp
#supplemental/versions-algorithm-data_dependency.cpp
effects-versions.cpp
)
add_executable(${PROJECT_NAME} ${TEST_FILES})
target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index ab020ca..2c5ce06 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,205 +1,204 @@
/* 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 "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, Variants_switch) {
XreateManager* man = XreateManager::prepare(R"Code(
Color = type variant{Blue, White, Green}.
main = function:: int {
x = White()::Color.
switch variant(x)::int
case (Green) {0}
case (White) {1}
case (Blue){2}
}
)Code");
Expression e = man->root->findFunction("main")->getEntryScope()->getBody();
ASSERT_EQ(4, e.getOperands().size());
ASSERT_EQ(3, e.blocks.size());
}
TEST(AST, DISABLED_InterfacesDataDFA) { }
TEST(AST, DISABLED_InterfacesDataExtern) { }
TEST(AST, Doc_LiteralsAndExpressions) {
XreateManager* man = XreateManager::prepare(
R"Code(
Record1 = type {year:: int, month:: string}.
isOdd = function(x :: int) :: bool {true}
test = function:: bool; entry {
x1 = 5 :: int.
x2 = "Nimefurahi kukujua":: string.
x3 = {year = 1934, month = "april"}:: Record1.
x4 = {16, 8, 3} :: [int].
x5 = 8>=3:: bool.
x6 = "Blue" <> "Green" :: 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"));
ASSERT_TRUE(true);
}
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);
- replace(code, "COUNTEREXAMPLE", "");
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_Variants){
string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Variants1");
XreateManager::prepare(move(code_Variants1));
ASSERT_TRUE(true);
}
\ No newline at end of file
diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp
index 472e186..b15a9e1 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,223 +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/DominatorsAnalysisProvider.h"
#include "analysis/cfagraph.h"
+#include "pass/cfatemporalseqpass.h"
+#include "analysis/temporalseqgraph.h"
#include "pass/compilepass.h"
#include "compilation/scopedecorators.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"
- "}";
+ 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();
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(program));
+ man->analyse();
- StaticModel answer = man->transcend->query("annotationF1");
- EXPECT_EQ(1, answer.size());
+ StaticModel answer = man->transcend->query("annotationF1");
+ EXPECT_EQ(1, answer.size());
- answer = man->transcend->query("annotationF2");
- 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);
+ 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, DependenciesFnCall) {
- details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
- R"Code(
- a = function::int{
- seq
- {x = 0:: int. x}
- {x = b():: 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();
-
- ScopePacked psSeq1 = man->transcend->pack(scopeSeq1);
- ScopePacked psSeq2 = man->transcend->pack(scopeSeq2);
- ScopePacked psB = man->transcend->pack(scopeB);
-
- CFAPass* pass = new CFAPass(man);
-
- man->registerPass(pass, PassId::CFAPass);
- man->executePasses();
- const CFAGraph* report = dynamic_cast<CFAPassBasic*> (man->getPassById(PassId::CFAPass))->getReport();
- auto dependencies = report->__dependencyRelations;
- delete pass;
+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
+ }
- ASSERT_EQ(1, dependencies.count(psSeq2));
- ASSERT_EQ(1, dependencies.count(psB));
+ 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, DependenciesChildScope) {
- details::tier2::XreateManager* man = details::tier2::XreateManager::prepare(
- R"Code(
+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);
-
- CFAPass* pass = new CFAPass(man);
-
- man->registerPass(pass, PassId::CFAPass);
- man->executePasses();
- const CFAGraph* report = dynamic_cast<CFAPassBasic*> (man->getPassById(PassId::CFAPass))->getReport();
- auto dependencies = report->__dependencyRelations;
- delete pass;
-
- ASSERT_EQ(0, dependencies.count(psSeq1));
- ASSERT_EQ(1, dependencies.count(psSeq2));
- ASSERT_EQ(1, dependencies.count(psIf1));
- ASSERT_EQ(1, dependencies.count(psIf2));
-
- for(auto rec : dependencies) {
- std::cout << rec.first << " " << rec.second << std::endl;
- }
-}
-
-TEST(CFA, Dominators1){
- std::multimap<ScopePacked, ScopePacked> dataScopes = {
- {1, 0}, {2, 0}, {3, 1}, {4, 1}, {4, 2}
- };
-
- dominators::DominatorsAnalysisProvider domProvider;
- boost::scoped_ptr<dominators::CFAGraphAdapter> adapter(dominators::CFAGraphAdapter::build(dataScopes));
- domProvider.run(adapter.get());
-
- dominators::DominatorsAnalysisProvider::Dominators expectedFDom= {
- {0, {0, 9}}
- ,{1, {1, 4}}
- ,{2, {7, 8}}
- ,{3, {2, 3}}
- ,{4, {5, 6}}
- };
-
- dominators::DominatorsAnalysisProvider::Dominators expectedPostDom= {
- {0, {5, 6}}
- ,{1, {3, 4}}
- ,{2, {8, 9}}
- ,{3, {1, 2}}
- ,{4, {7, 10}}
- };
-
- ASSERT_EQ(expectedFDom, domProvider.getForwardDominators());
- ASSERT_EQ(expectedPostDom, domProvider.getPostDominators());
+ 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, Dominators2) {
- std::string program =
- R"CODE(
- a = function:: int; entry{
- seq
- {x = 0:: int. x}
- {x = 1:: int. x}::int
- }
-)CODE";
-
- std::unique_ptr<details::tier2::XreateManager> man(details::tier2::XreateManager::prepare(move(program)));
-
- CFAPass* pass = new CFAPass(man.get());
- man->registerPass(pass, PassId::CFAPass);
- pass->run();
-
- ScopePacked scope1 = man->transcend->pack(man->root->findFunction("a")->getEntryScope()->getBody().blocks.front());
- ScopePacked scope2 = man->transcend->pack(*++man->root->findFunction("a")->getEntryScope()->getBody().blocks.begin());
-
- dominators::DominatorsAnalysisProvider* providerDomAnalysis = new dominators::DominatorsAnalysisProvider();
- boost::scoped_ptr<dominators::CFAGraphAdapter> adapter(dominators::CFAGraphAdapter::build(pass->getReport()));
- providerDomAnalysis->run(adapter.get());
-
- dominators::DominatorsAnalysisProvider::Dominators expectedFDom = {
- {1, {0, 3}},
- {2, {1, 2}}
- };
-
- dominators::DominatorsAnalysisProvider::Dominators expectedPostDom = {
- {2, {1, 4}},
- {1, {2, 3}}
- };
-
- auto actualFDom = providerDomAnalysis->getForwardDominators();
- auto actualPostDom = providerDomAnalysis->getPostDominators();
-
- ASSERT_EQ(expectedFDom, actualFDom);
- ASSERT_EQ(expectedPostDom, actualPostDom);
+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");
- delete providerDomAnalysis;
- delete pass;
-}
+ 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/exploitation.cpp b/cpp/tests/exploitation.cpp
index 9ac2d1d..217f1a4 100644
--- a/cpp/tests/exploitation.cpp
+++ b/cpp/tests/exploitation.cpp
@@ -1,25 +1,38 @@
/* 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 "gtest/gtest.h"
using namespace xreate;
+using namespace xreate::cfa;
+using namespace std;
-TEST(Exploitation, test1){
- FILE* input = fopen("scripts/exploitation/test1.xreate","r");
- assert(input != nullptr);
+TEST(Exploitation, Doc_ResourceInit_1) {
+ string example = getDocumentationExampleFromFile("scripts/exploitation/test1.xreate");
+ string body = getDocumentationExampleById("documentation/exploitation.xml", "ResourceInit_1");
+ replace(example, "<BODY>", body);
- std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
+ 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();
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
+ delete pass;
+ delete man;
- ASSERT_EQ(1, result);
+ ASSERT_EQ(1, result);
}
\ No newline at end of file
diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp
index a032b19..4609b15 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,568 +1,485 @@
/* 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(
+TEST(Interpretation, Analysis_StatementIF_1) {
+ XreateManager* man = XreateManager::prepare(
-R"Code(
+ R"Code(
main = function::bool {
x = "a":: string.
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, Doc_Compilation_StatementIF_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-
-R"Code(
- main= function:: int; entry
- {
- x= "a"::string.
-
- y= if (x=="b")::string; i12n(on)
- {1} else {0}.
- y
- }
-)Code" );
-
- man->analyse();
-
- InterpretationPass* pass;
- if (man->isPassRegistered(PassId::InterpretationPass)){
- pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
- } else {
- pass = new InterpretationPass(man);
- pass->run();
- }
+)Code");
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
- int (*main)() = (int (*)())man->run();
- int result = main();
+ CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
+ Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
+ InterpretationData &dataSymbolY = Attachments::get<InterpretationData>(symbolY);
- ASSERT_EQ(0, result);
+ ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution);
}
-TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1){
- XreateManager* man = XreateManager::prepare(
+TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1) {
+ XreateManager* man = XreateManager::prepare(
-R"Code(
+ R"Code(
main = function(x:: int):: int {
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, Doc_Compilation_StatementIF_InterpretCondition_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-
-R"Code(
- test = function(x:: int):: int; entry {
- comm= "inc":: string; i12n(on).
-
- y= if (comm == "inc"):: int
- {x + 1} else {x}.
- y
- }
-)Code" );
-
- 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_Compilation_StatementFOLD_INTERPRET_INPUT_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-
-R"Code(
- main = function(x:: int):: int; entry {
- commands = {"inc", "double", "dec"}:: [string]; i12n(on).
-
- loop fold(commands->comm::string, x->operand):: int
- {
- switch(comm):: int
- case ("inc") {operand + 1}
- case ("dec") {operand - 1}
- case ("double") {operand * 2}
- }
- }
-)Code" );
-
- 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);
-}
-
-TEST(Interpretation, Doc_StatementCall_RecursionNo_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"Code(
- unwrap = function(data::unknType, keys::unknType):: unknType; i12n(on)
- {
- loop fold(keys->key::string, data->record):: unknType
- {
- record[key]
- }
- }
-
- test = function:: bool; entry
- {
- book = unwrap({
- Library = {
- Shelf = {
- Book = "Aristotle's Politics"
- }}}, {"Library", "Shelf", "Book"}):: unknType.
-
- book == "Aristotle's Politics"
- }
-)Code" );
-
- 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_StatementCall_RecursionNo_2){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"Code(
- unwrap = function(data::unknType, keys::unknType):: unknType
- {
- loop fold(keys->key::string, data->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"
- }
-)Code" );
-
- man->analyse();
+)Code");
- InterpretationPass* pass;
- if (man->isPassRegistered(PassId::InterpretationPass)){
- pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
- } else {
- pass = new InterpretationPass(man);
- pass->run();
- }
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
- unsigned char (*main)() = (unsigned char (*)())man->run();
- unsigned char result = main();
+ CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
+ Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
+ InterpretationData &dataSymbolY = Attachments::get<InterpretationData>(symbolY);
- ASSERT_EQ(1, result);
+ ASSERT_EQ(CMPL_ONLY, dataSymbolY.resolution);
+ ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
}
-TEST(Interpretation, Doc_StatementCall_RecursionDirect_1){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"Code(
- 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)
- }
-)Code" );
-
- 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, StatementCall_RecursionIndirect_1){
- XreateManager* man = XreateManager::prepare(
-R"Code(
+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)
}
-)Code" );
+)Code");
- InterpretationPass* pass = new InterpretationPass(man);
- ASSERT_DEATH(pass->run(), "Indirect recursion detected");
+ InterpretationPass* pass = new InterpretationPass(man);
+ ASSERT_DEATH(pass->run(), "Indirect recursion detected");
}
-TEST(Interpretation, PartialIntr_1){
- XreateManager* man = XreateManager::prepare(
-R"Code(
+TEST(Interpretation, PartialIntr_1) {
+ XreateManager* man = XreateManager::prepare(
+ R"Code(
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:: 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, Doc_Compilation_PartialIntr_2){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"Code(
-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->comm::string, init->operand):: int
- {
- evaluate(operand, comm)
- }
-}
-)Code" );
+)Code");
- man->analyse();
- if (!man->isPassRegistered(PassId::InterpretationPass)){
- InterpretationPass* pass = new InterpretationPass(man);
- pass->run();
- }
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
- int (*main)(int) = (int (*)(int))man->run();
- int result = main(10);
+ ManagedFnPtr fnEvaluate = man->root->findFunction("evaluate");
+ InterpretationResolution resFnEvaluate = pass->process(fnEvaluate);
+ ASSERT_EQ(CMPL_ONLY, resFnEvaluate);
+ ASSERT_TRUE(FunctionInterpretationHelper::needPartialInterpretation(fnEvaluate));
- ASSERT_EQ(21, result);
+ 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(
+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 {
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).
loop fold(commands->comm::Command, 10->operand):: int{
evaluate(operand, comm)
}
}
-)Code" );
+)Code");
- man->analyse();
- if (!man->isPassRegistered(PassId::InterpretationPass)){
- InterpretationPass* pass = new InterpretationPass(man);
- pass->run();
- }
+ man->analyse();
+ if(!man->isPassRegistered(PassId::InterpretationPass)) {
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
+ }
- int (*main)() = (int (*)())man->run();
- int result = main();
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
- ASSERT_EQ(21, result);
+ ASSERT_EQ(21, result);
}
-TEST(Interpretation, PartialIntr_4){
- xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
-R"Code(
+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
case (INC) {argument + 1}
case (DEC) {argument - 1}
case (DOUBLE) {argument * 2}
}
main = function::int; entry {
evaluate(4, DEC())
}
-)Code" );
+)Code");
- man->analyse();
- if (!man->isPassRegistered(PassId::InterpretationPass)){
- InterpretationPass* pass = new InterpretationPass(man);
- pass->run();
- }
+ man->analyse();
+ if(!man->isPassRegistered(PassId::InterpretationPass)) {
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
+ }
- int (*main)() = (int (*)())man->run();
- int result = main();
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
- ASSERT_EQ(3, result);
+ ASSERT_EQ(3, result);
}
-TEST(Interpretation, SwitchVariant){
- xreate::XreateManager* man = xreate::XreateManager::prepare(
-R"Code(
+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
}.
main = function::int; entry{
program = ADD({x=2, y=3})::Command; i12n(on).
switch variant(program)::int
case (ADD) {program["x"]+program["y"]}
case (DEC) {1}
case (DOUBLE) {2}
}
-)Code" );
+)Code");
- int (*main)() = (int (*)())man->run();
- int result = main();
- ASSERT_EQ(5, result);
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
+ ASSERT_EQ(5, result);
}
-TEST(Interpretation, SwitchVariantAlias){
- xreate::XreateManager* man = xreate::XreateManager::prepare(
-R"Code(
+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
}.
main = function::int; entry{
program = {ADD({x=2, y=3}), DEC({x=8})}::[Command]; i12n(on).
switch variant(program[0]->program::Command)::int
case (ADD) {program["x"]+program["y"]}
case (DEC) {1}
case (DOUBLE) {2}
}
-)Code" );
+)Code");
- int (*main)() = (int (*)())man->run();
- int result = main();
- ASSERT_EQ(5, result);
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
+ ASSERT_EQ(5, result);
}
-TEST(Interpretation, Multiindex1){
- std::string script2=
-R"Code(
+TEST(Interpretation, Multiindex1) {
+ std::string script2 =
+ R"Code(
extract = function(program::unknType)::int; i12n(on){
program["arguments"][1]
}
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)));
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script2)));
- int (*main)() = (int (*)())man->run();
- int result = main();
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
- ASSERT_EQ(9, result);
+ ASSERT_EQ(9, result);
}
-TEST(InterpretationExamples, Regexp1){
- FILE* input = fopen("scripts/dsl/regexp.xreate","r");
- assert(input != nullptr);
+TEST(InterpretationExamples, Regexp1) {
+ FILE* input = fopen("scripts/dsl/regexp.xreate", "r");
+ assert(input != nullptr);
- std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
- int (*main)() = (int (*)())man->run();
- int result = main();
+ int (* main)() = (int (*)()) man->run();
+ int result = main();
- ASSERT_EQ(4, result);
+ ASSERT_EQ(4, result);
}
-TEST(Interpretation, Variant1){
- std::string script=
-R"Code(
+TEST(Interpretation, Variant1) {
+ std::string script =
+ R"Code(
Data = type {Num:: [int], String::string}.
DataPacked = type variant {
Var1:: Data,
Var2:: Data
}.
extractInt = function(data::DataPacked):: int {
resultWrong = 0 :: int.
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.
extractInt(dataPacked):: int; i12n(on)
}
)Code";
- std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
+ 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);
- int (*main)() = (int (*)())man->run();
- int result = main();
+ ASSERT_EQ(21, result);
- ASSERT_EQ(10, 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/latetranscend.cpp b/cpp/tests/latetranscend.cpp
index 51d3666..0c02ef8 100644
--- a/cpp/tests/latetranscend.cpp
+++ b/cpp/tests/latetranscend.cpp
@@ -1,208 +1,122 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 21, 2018, 5:10 PM
*/
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "pass/latereasoningpass.h"
#include "aux/latereasoning.h"
-#include "pass/dfapass.h"
-#include <boost/format.hpp>
+#include "supplemental/docutils.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate;
using namespace xreate::latereasoning;
TEST(LateReasoning, Syntax1) {
- XreateManager* man = XreateManager::prepare(R"Code(
+ XreateManager* man = XreateManager::prepare(R"Code(
test = function:: int {
x = 0::int.
y1= switch late (x)::int{0}.
y2= switch late(x+y1->a::int)::int{1}.
y1+y2
}
)Code");
- CodeScope* scope = man->root->findFunction("test")->getEntryScope();
- Expression y1 = scope->getDefinition(scope->getSymbol("y1"));
- Expression y2 = scope->getDefinition(scope->getSymbol("y2"));
+ CodeScope* scope = man->root->findFunction("test")->getEntryScope();
+ Expression y1 = scope->getDefinition(scope->getSymbol("y1"));
+ Expression y2 = scope->getDefinition(scope->getSymbol("y2"));
- ASSERT_EQ(1, y1.bindings.size());
- ASSERT_STRCASEEQ("x", y1.bindings.at(0).c_str());
+ ASSERT_EQ(1, y1.bindings.size());
+ ASSERT_STRCASEEQ("x", y1.bindings.at(0).c_str());
- ASSERT_EQ(1, y2.bindings.size());
- ASSERT_STRCASEEQ("a", y2.bindings.at(0).c_str());
+ ASSERT_EQ(1, y2.bindings.size());
+ ASSERT_STRCASEEQ("a", y2.bindings.at(0).c_str());
}
-TEST(LateReasoning, Pass_DFAPassDec_1){
- typedef LateReasoningTranscendDecorator<TranscendLayer> LRTranscend;
+TEST(LateReasoning, Pass_DFAPassDec_1) {
+ typedef LateReasoningTranscendDecorator<TranscendLayer> LRTranscend;
- auto man = details::tier2::XreateManager::prepare(R"Code(
+ auto man = details::tier2::XreateManager::prepare(R"Code(
Dom = type slave dom.
test = function:: int; entry
{
LateIdent = 0:: Dom.
0:: int; ann1(LateIdent)
}
)Code");
- CodeScope* scopeEntry = man->root->findFunction("test")->getEntryScope();
- ScopedSymbol keyS = scopeEntry->getSymbol("LateIdent");
- SymbolPacked keySP = man->transcend->pack(Symbol{keyS, scopeEntry});
-
- std::shared_ptr<LateReasoningScope> scopeLateEntry(new LateReasoningScope(nullptr));
- scopeLateEntry->addIdentifier("LateIdent", keySP);
-
- typedef LateReasoningDFAPassDecorator<dfa::DFAPass> LRDFAPass;
- LRDFAPass* dfaPass = new LRDFAPass(man);
- dfaPass->registerLateScope(scopeEntry, scopeLateEntry.get());
-
- man->transcend->addRawScript("dom(guard1; guard2).\n");
-
- man->registerPass(dfaPass, PassId::DFAPass, nullptr);
- man->executePasses();
-
- testing::internal::CaptureStdout();
- man->analyse();
- std::string outputActual = testing::internal::GetCapturedStdout();
- cout << outputActual << endl;
-
- string outputExpected = "late(s(0,-2,0), (s(1,-2,0)), (LateIdent), ann1(LateIdent)):- dom(LateIdent).";
- ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+ CodeScope* scopeEntry = man->root->findFunction("test")->getEntryScope();
+ ScopedSymbol keyS = scopeEntry->getSymbol("LateIdent");
+ SymbolPacked keySP = man->transcend->pack(Symbol{keyS, scopeEntry});
+
+ std::shared_ptr<LateReasoningScope> scopeLateEntry(new LateReasoningScope(nullptr));
+ scopeLateEntry->addIdentifier("LateIdent", keySP);
+
+ typedef LateReasoningDFAPassDecorator<dfa::DFAPass> LRDFAPass;
+ LRDFAPass* dfaPass = new LRDFAPass(man);
+ dfaPass->registerLateScope(scopeEntry, scopeLateEntry.get());
+
+ man->transcend->addRawScript("dom(guard1; guard2).\n");
+
+ man->registerPass(dfaPass, PassId::DFAPass, nullptr);
+ man->executePasses();
+
+ testing::internal::CaptureStdout();
+ man->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual << endl;
+
+ string outputExpected = "late(s(0,-2,0), (s(1,-2,0)), (LateIdent), ann1(LateIdent)):- dom(LateIdent).";
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
}
-//TEST(LateReasoning, Transcend_LRTransDec_1) {
-// Attachments::init<versions::VariableVersion>();
-// typedef LateReasoningTranscendDecorator<TranscendLayer> LRTranscend;
-// std::unique_ptr<LRTranscend> transcend(new LRTranscend());
-
-// std::unique_ptr<CodeScope> scope(new CodeScope(nullptr));
-// Symbol symbA = scope->addDefinition(Atom<Identifier_t>("a"), Expression());
-// Symbol symbB = scope->addDefinition(Atom<Identifier_t>("b"), Expression());
-// Symbol symbC = scope->addDefinition(Atom<Identifier_t>("c"), Expression());
-// Symbol symbTarget1 = scope->addDefinition(Atom<Identifier_t>("target1"), Expression());
-// Symbol symbTarget2 = scope->addDefinition(Atom<Identifier_t>("target2"), Expression());
-
-// SymbolPacked symbpA = transcend->pack(symbA, "a");
-// SymbolPacked symbpB = transcend->pack(symbB, "b");
-// SymbolPacked symbpC = transcend->pack(symbC, "c");
-// SymbolPacked symbTarget1P = transcend->pack(symbTarget1, "target1");
-// SymbolPacked symbTarget2P = transcend->pack(symbTarget2, "target2");
-
-// boost::format formatSymb("s(%1%,%2%,%3%)");
-// boost::format formatLateAnnotation1("late(%1%, (%2%, %3%, %4%), (%5%, %6%, %7%), %8%).");
-// boost::format formatLateAnnotation2("late(%1%, (%2%, %3%), (%4%, %5%), %6%).");
-// #define FORMATSYMBOL(s) (formatSymb % s.identifier % s.version % s.scope).str()
-
-// // Ann1, `variant1`
-// transcend->addRawScript((formatLateAnnotation1
-// % FORMATSYMBOL(symbTarget1P)
-// % FORMATSYMBOL(symbpA) % FORMATSYMBOL(symbpB) % FORMATSYMBOL(symbpC)
-// % "guard1" % "guard1" % "guard1"
-// % "result(variant1)"
-// ). str());
-
-// //Ann1 `result2` variant
-// transcend->addRawScript((formatLateAnnotation1
-// % FORMATSYMBOL(symbTarget1P)
-// % FORMATSYMBOL(symbpA) % FORMATSYMBOL(symbpB) % FORMATSYMBOL(symbpC)
-// % "guard2" % "guard2" % "guard2"
-// % "result(variant2)"
-// ). str());
-
-// //Ann2 `result3` variant
-// transcend->addRawScript((formatLateAnnotation2
-// % FORMATSYMBOL(symbTarget2P)
-// % FORMATSYMBOL(symbpA) % FORMATSYMBOL(symbpB)
-// % "guard3" % "guard3"
-// % "result(variant3)"
-// ). str());
-
-// transcend->run();
-// LateAnnotationsGroup group = transcend->queryLate("result");
-// ASSERT_EQ(2, group.annotations.size());
-
-// for(const auto& annEntry: group.annotations){
-// annEntry.first.print(cout);
-// cout <<endl;
-
-// Gringo::SymSpan symbsTuple;
-// symbsTuple.first = &annEntry.first;
-// symbsTuple.size = 1;
-// Gringo::Symbol targetWrapped = Gringo::Symbol::createTuple(symbsTuple);
-// SymbolPacked targetSP = get<0>(transcend->parse<SymbolPacked>(targetWrapped));
-// if (targetSP == symbTarget1P){
-// LateAnnotation ann = annEntry.second;
-// ASSERT_EQ(2, ann.guardedContent.size());
-
-// Expression selector(Operator::CALL, {Atom<Identifier_t>("guard2")});
-// auto answer = ann.select({selector, selector, selector}, man->root, man->transcend);
-// ASSERT_TRUE(answer);
-// string answerS = get<0>(transcend->parse<string>(*answer));
-// ASSERT_STREQ("variant2", answerS.c_str());
-
-// } else if (targetSP == symbTarget2P) {
-// LateAnnotation ann = annEntry.second;
-// ASSERT_EQ(1, ann.guardedContent.size());
-
-// Expression selector(Operator::CALL, {Atom<Identifier_t>("guard3")});
-// auto answer = ann.select({selector, selector, selector});
-// ASSERT_TRUE(answer);
-// ASSERT_STREQ("variant3", get<0>(transcend->parse<string>(*answer)).c_str());
-
-// } else {
-// ASSERT_TRUE(false);
-// }
-// }
-//}
-
-TEST(LateReasoning, Doc_SwitchLateOperation){
- auto man = details::tier2::XreateManager::prepare(
-R"Code(
-
-mul = function(x::float, y::float):: float
+TEST(LateReasoning, Doc_SwitchLateOperation) {
+ string example = R"Code(
+mul = function(x::float, y::float):: float
{
x * y
}
+<BODY>
+)Code";
-ArithmeticT = type slave arithmetic.
+ string codeTranscend =
+ R"Code(
+arithmetic(fast; accurate).
+)Code";
-test = function(a::float, b::float, ArithmX::ArithmeticT):: float; entry
-{
- switch late (ArithmX):: float
- {
- mul(a, b)::float; arithmetic(ArithmX)
- }
-}
+ string example_LateAnn_1 = getDocumentationExampleById("documentation/Transcend/latetranscend.xml", "LateAnn_1");
+ string example_SwitchLate_1 = getDocumentationExampleById("documentation/Transcend/latetranscend.xml", "SwitchLate_1");
+ string outputExpected = getDocumentationExampleById("documentation/Transcend/latetranscend.xml", "Output_LateAnn_1");
+ replace(example, "<BODY>", example_SwitchLate_1);
-)Code");
-
- string codeTranscend =
-R"Code(
- arithmetic(fast; accurate).
-)Code";
-
- typedef LateReasoningTranscendDecorator<TranscendLayer> LateTranscend;
- typedef LateReasoningDFAPassDecorator<dfa::DFAPass> LTDFAPass;
-
- std::unique_ptr<LateTranscend> transcend(new LateTranscend());
- man->transcend = transcend.get();
- man->transcend->addRawScript(move(codeTranscend));
- LTDFAPass* pass = new LTDFAPass(man);
-
- man->registerPass(pass, PassId::DFAPass, nullptr);
- man->executePasses();
- man->analyse();
-
- auto result = transcend->queryLate("arithmetic");
- ASSERT_EQ(1, result.annotations.size());
- ASSERT_EQ(2, result.annotations.begin()->second.guardedContent.size());
- //man->run();
+ ASSERT_NE(std::string::npos, example_SwitchLate_1.find(example_LateAnn_1));
+
+ typedef LateReasoningTranscendDecorator<TranscendLayer> LateTranscend;
+ typedef LateReasoningDFAPassDecorator<dfa::DFAPass> LTDFAPass;
+
+ auto man = details::tier2::XreateManager::prepare(move(example));
+ std::unique_ptr<LateTranscend> transcend(new LateTranscend());
+ man->transcend = transcend.get();
+ man->transcend->addRawScript(move(codeTranscend));
+ LTDFAPass* pass = new LTDFAPass(man);
+
+ man->registerPass(pass, PassId::DFAPass, nullptr);
+ man->executePasses();
+
+ testing::internal::CaptureStdout();
+ man->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual << endl;
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+
+ auto result = transcend->queryLate("arithmetic");
+ ASSERT_EQ(1, result.annotations.size());
+ ASSERT_EQ(2, result.annotations.begin()->second.guardedContent.size());
}
diff --git a/cpp/tests/supplemental/docutils.cpp b/cpp/tests/supplemental/docutils.cpp
index 627daf4..6fac2ad 100644
--- a/cpp/tests/supplemental/docutils.cpp
+++ b/cpp/tests/supplemental/docutils.cpp
@@ -1,54 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* \file docutils.cpp
* \brief Documentation processing
*
*/
#include "docutils.h"
#include <iostream>
+#include <fstream>
#include <assert.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
using namespace std;
std::string
getDocumentationExampleById(std::string filename, std::string id) {
- string query = string("(//db:programlisting | //db:code)[@xml:id='") + id + "']";
+ string query = string("(//db:programlisting | //db:code | //db:screen)[@xml:id='") + id + "']";
xmlDocPtr doc = xmlParseFile(filename.c_str());
- if (!doc) {
+ if(!doc) {
cout << "Can't find documentation file: " << filename << endl;
assert(false);
return "";
}
xmlXPathContextPtr context = xmlXPathNewContext(doc);
- xmlXPathRegisterNs(context, BAD_CAST "db", BAD_CAST "http://docbook.org/ns/docbook");
+ xmlXPathRegisterNs(context, BAD_CAST "db", BAD_CAST "http://docbook.org/ns/docbook");
xmlXPathObjectPtr response = xmlXPathEvalExpression((xmlChar*) query.c_str(), context);
xmlXPathFreeContext(context);
xmlNodeSetPtr nodeset = response->nodesetval;
- if (nodeset->nodeNr != 1) {
+ if(nodeset->nodeNr != 1) {
cout << "Can't find specified example " << id << endl;
assert(false);
return "";
}
+ string tag = (char*) nodeset->nodeTab[0]->name;
+ bool flagIsPrgListing = tag == "programlisting";
xmlChar* contentC = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1);
string content = (char*) contentC;
xmlFree(contentC);
- xmlXPathFreeObject (response);
+ xmlXPathFreeObject(response);
+ if(flagIsPrgListing){
+ //skip first line(used as header)
+ content = content.substr(content.find('\n')+1);
+ }
assert(content.size() && "Empty example");
return content;
}
+std::string
+getDocumentationExampleFromFile(std::string filename) {
+ std::ifstream stream(filename);
+ std::string result;
+
+ stream.seekg(0, std::ios::end);
+ result.reserve(stream.tellg());
+ stream.seekg(0, std::ios::beg);
+
+ result.assign((std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>());
+
+ assert(result.size() && "Empty example");
+
+ return result;
+}
+
void
-replace(std::string& str, const std::string& subA, const std::string& subB) {
- str.replace(str.find(subA), subA.size(), subB);
+replace(std::string &str, const std::string &subA, const std::string &subB) {
+ size_t posA = str.find(subA);
+ assert(posA != string::npos);
+
+ str.replace(posA, subA.size(), subB);
}
\ No newline at end of file
diff --git a/cpp/tests/supplemental/docutils.h b/cpp/tests/supplemental/docutils.h
index c6c50f4..3f17d8f 100644
--- a/cpp/tests/supplemental/docutils.h
+++ b/cpp/tests/supplemental/docutils.h
@@ -1,21 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* File: docuils.h
* Author: pgess
*
* Created on November 29, 2018, 3:58 PM
*
- * \brief Documentation processing\
+ * \brief Documentation processing
*/
#ifndef DOC_H
#define DOC_H
#include <string>
-std::string getDocumentationExampleById(std::string filename, std::string id);
-void replace(std::string& str, const std::string& subA, const std::string& subB);
+std::string getDocumentationExampleById (std::string filename, std::string id);
+std::string getDocumentationExampleFromFile (std::string filename);
+void replace (std::string& str,
+ const std::string& subA,
+ const std::string& subB);
#endif /* DOC_H */
diff --git a/cpp/tests/transcend-ast.cpp b/cpp/tests/transcend-ast.cpp
new file mode 100644
index 0000000..c8c6044
--- /dev/null
+++ b/cpp/tests/transcend-ast.cpp
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * AST-Transcend Correspondence Tests
+ *
+ * Created on: Dec 2, 2018
+ * Author: pgess <v.melnychenko@xreate.org>
+ */
+
+#include <pass/cfapass.h>
+#include "xreatemanager.h"
+#include "pass/dfapass.h"
+#include "supplemental/docutils.h"
+
+#include <boost/algorithm/string.hpp>
+#include "gtest/gtest.h"
+
+using namespace xreate;
+using namespace std;
+
+struct TestRec {
+ string refExample;
+ string refOutput;
+ PassId pass;
+};
+
+std::list<TestRec> tests = {
+ {"ExprAnn_1", "Output_ExprAnn_1", PassId::DFAPass},
+ {"CodeBlock_1", "Output_CodeBlock_1", PassId::CFAPass},
+ {"CodeBlockAnns_1", "Output_CodeBlockAnns_1", PassId::CFAPass},
+ {"CodeBlockBinds_1", "Output_CodeBlockBinds_1", PassId::CFAPass},
+ {"CodeBlockParents_1", "Output_CodeBlockParents_1",PassId::CFAPass},
+ {"Fn_1", "Output_Fn_1", PassId::CFAPass},
+ {"FnAnns_1", "Output_FnAnns_1", PassId::CFAPass},
+ {"FnSpecs_1", "Output_FnSpecs_1", PassId::CFAPass},
+ {"FnEntry_1", "Output_FnEntry_1", PassId::CFAPass},
+ {"FnResult_1", "Output_FnResult_1", PassId::CFAPass},
+ {"OpInvoc_1", "Output_OpInvoc_1", (PassId) 1000},
+ {"OpLoops_1", "Output_OpLoops_1", PassId::DFAPass}
+};
+
+TEST(ASTCorrespondence, Doc_BasicTests) {
+ for(auto test: tests) {
+ string program = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refExample);
+ string outputExpected = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refOutput);
+
+ std::unique_ptr<details::tier2::XreateManager> man(details::tier2::XreateManager::prepare(move(program)));
+ switch(test.pass) {
+ case PassId::CFAPass:
+ man->registerPass(new cfa::CFAPass(man.get()), test.pass);
+ break;
+ case PassId::DFAPass:
+ man->registerPass(new dfa::DFAPass(man.get()), test.pass);
+ break;
+ default:
+ man->registerPass(new dfa::DFAPass(man.get()), PassId::DFAPass);
+ man->registerPass(new cfa::CFAPass(man.get()), PassId::CFAPass);
+ break;
+ }
+ man->registerPass(new dfa::DFAPass(man.get()), test.pass);
+ man->executePasses();
+
+ cout << "Test: " << test.refExample << endl;
+ testing::internal::CaptureStdout();
+ man->analyse();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ //cout << outputActual << endl;
+
+ //check every line independently if outputActual is multi-line string
+ std::vector<std::string> lines;
+ boost::split(lines, outputExpected, [](char c){return c == '\n';});
+ for(auto line: lines) {
+ ASSERT_NE(std::string::npos, outputActual.find(line));
+ }
+ }
+}
+
diff --git a/cpp/tests/virtualization.cpp b/cpp/tests/virtualization.cpp
index 033a706..a4eb9c7 100644
--- a/cpp/tests/virtualization.cpp
+++ b/cpp/tests/virtualization.cpp
@@ -1,60 +1,72 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* virtualization.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on February 24, 2018, 4:30 PM
*/
#include "xreatemanager.h"
#include "ast.h"
#include "analysis/interpretation.h"
#include "gtest/gtest.h"
+#include "supplemental/docutils.h"
+
using namespace xreate;
using namespace std;
-TEST(Virtualization, UniqueSizoPrefix_1) {
- FILE* input = fopen("scripts/virtualization/test1.xreate", "r");
- assert(input != nullptr);
-
- std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(input));
- man->analyse();
-
- ExpandedType typeDictSizoS = man->root->findType("DictSizo");
- ExpandedType typeDictSizo = interpretation::dereferenceSlaveType(typeDictSizoS, man->transcend);
- ASSERT_EQ(TypeOperator::LIST_RECORD, typeDictSizo->__operator);
- int (*main)() = (int (*)())man->run();
-
- testing::internal::CaptureStdout();
- main();
- std::string outputActual = testing::internal::GetCapturedStdout();
- cout << outputActual << endl;
- ASSERT_STREQ("file opened: /0/test1 file opened: /1/test1 ", outputActual.c_str());
-}
+TEST(Virtualization, Doc_AccControl_1) {
+ string example = getDocumentationExampleFromFile("scripts/virtualization/test-AccControl_1.xreate");
+ string exampleBody = getDocumentationExampleById("documentation/virtualization.xml", "AccControl_1");
+ string output = getDocumentationExampleById("documentation/virtualization.xml", "Output_AccControl_1");
+ replace(example, "<BODY>", exampleBody);
+
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(move(example)));
+ int (* main)() = (int (*)()) man->run();
-TEST(Virtualization, GlobalDereferenceStrategy_1) {
- FILE* input = fopen("scripts/virtualization/test2.xreate", "r");
- assert(input != nullptr);
- std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
- int (*main)() = (int (*)())man->run();
-
- testing::internal::CaptureStdout();
- main();
- std::string outputActual = testing::internal::GetCapturedStdout();
- cout << outputActual << endl;
- ASSERT_STREQ("file opened: test1 file opened: test1 ", outputActual.c_str());
+ testing::internal::CaptureStdout();
+ main();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual << endl;
+ ASSERT_STREQ(output.c_str(), outputActual.c_str());
}
-TEST(Virtualization, LocalDereferenceStrategy_1) {
-FILE* input = fopen("scripts/virtualization/test3.xreate", "r");
- assert(input != nullptr);
- std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
- int (*main)() = (int (*)())man->run();
-
- testing::internal::CaptureStdout();
- main();
- std::string outputActual = testing::internal::GetCapturedStdout();
- cout << outputActual << endl;
- ASSERT_STREQ("file opened: test1 file opened: 1/test1 ", outputActual.c_str());
+TEST(Virtualization, Doc_Isolation_1) {
+ string example = getDocumentationExampleFromFile("scripts/virtualization/test-Isolation_1.xreate");
+ string partA = getDocumentationExampleById("documentation/virtualization.xml", "Isolation_1");
+ string partB = getDocumentationExampleById("documentation/virtualization.xml", "Isolation_2");
+ string output = getDocumentationExampleById("documentation/virtualization.xml", "Output_Isolation_1");
+ replace(example, "<PART-A-BODY>", partA);
+ replace(example, "<PART-B-BODY>", partB);
+
+ std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(example)));
+ man->analyse();
+
+ ExpandedType typeDictSizoS = man->root->findType("DictSizo");
+ ExpandedType typeDictSizo = interpretation::dereferenceSlaveType(typeDictSizoS, man->transcend);
+ ASSERT_EQ(TypeOperator::LIST_RECORD, typeDictSizo->__operator);
+ int (* main)() = (int (*)()) man->run();
+
+ testing::internal::CaptureStdout();
+ main();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual << endl;
+ ASSERT_STREQ(output.c_str(), outputActual.c_str());
}
+
+TEST(Virtualization, Doc_IsolationCat_1) {
+ string content = getDocumentationExampleFromFile("scripts/virtualization/test-IsolationCat_1.xreate");
+ string example = getDocumentationExampleById("documentation/virtualization.xml", "IsolationCat_1");
+ string output = getDocumentationExampleById("documentation/virtualization.xml", "Output_IsolationCat_1");
+ replace(content, "<EXAMPLE>", example);
+
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(move(content)));
+ int (* main)() = (int (*)()) man->run();
+
+ testing::internal::CaptureStdout();
+ main();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ cout << outputActual << endl;
+ ASSERT_STREQ(output.c_str(), outputActual.c_str());
+}
\ No newline at end of file
diff --git a/documentation-api/exploitation.graphml b/documentation-api/exploitation.graphml
new file mode 100644
index 0000000..1eb1f56
--- /dev/null
+++ b/documentation-api/exploitation.graphml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+ <!--Created by yEd 3.18.1-->
+ <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+ <key for="port" id="d1" yfiles.type="portgraphics"/>
+ <key for="port" id="d2" yfiles.type="portgeometry"/>
+ <key for="port" id="d3" yfiles.type="portuserdata"/>
+ <key attr.name="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="com.yworks.bpmn.Pool">
+ <y:Geometry height="604.1693115234376" width="777.8818359375" x="599.1513671875" y="23.000000000000114"/>
+ <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="81.548828125" x="4.0" xml:space="preserve" y="261.3102416992188">Exploitation</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="53.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="238.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="491.9092407226566">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="131" bottomF="131.0" left="0" leftF="0.0" right="504" rightF="504.38455093750053" top="36" topF="35.999999999999886"/>
+ <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="724.8818359375">
+ <y:Insets bottom="3.0" left="3.0" right="3.0" top="20.0"/>
+ </y:Column>
+ </y:Columns>
+ <y:Rows>
+ <y:Row height="107.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="286.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="187.83068847656216" 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="n0:">
+ <node id="n0::n0">
+ <data key="d6">
+ <y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
+ <y:Geometry height="34.0" width="86.697265625" x="649.1513671875" y="459.1693115234377"/>
+ <y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" 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="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.697265625" x="5.0" xml:space="preserve" y="8.296875">expl_siteUser<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="n0::n1">
+ <data key="d6">
+ <y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
+ <y:Geometry height="30.0" width="77.369140625" x="751.5048828125" y="461.1693115234377"/>
+ <y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" 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="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="67.369140625" x="5.0" xml:space="preserve" y="6.296875">expl_siteInit<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="n0::n2">
+ <data key="d6">
+ <y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
+ <y:Geometry height="30.0" width="110.052734375" x="759.5959178124995" y="79.0"/>
+ <y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" 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="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="100.052734375" x="5.0" xml:space="preserve" y="6.296875">expl_assignments<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="n0::n3">
+ <data key="d5"/>
+ <data key="d6">
+ <y:GenericNode configuration="com.yworks.flowchart.cloud">
+ <y:Geometry height="66.0" width="99.76523437500009" x="764.7396678124994" y="297.68465576171894"/>
+ <y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
+ <y:BorderStyle color="#000000" type="line" width="1.0"/>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="47.365234375" x="26.200000000000045" xml:space="preserve" y="24.296875">Payload<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+ </y:GenericNode>
+ </data>
+ </node>
+ <node id="n0::n4">
+ <data key="d6">
+ <y:GenericNode configuration="com.yworks.bpmn.Activity.withShadow">
+ <y:Geometry height="30.0" width="85.37890625" x="771.9328318749995" y="226.1014449999999"/>
+ <y:Fill color="#FFFFFFE6" color2="#D4D4D4CC" 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="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="75.37890625" x="5.0" xml:space="preserve" y="6.296875">expl_supdom<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>
+ <edge id="e0" source="n0::n0" target="n0">
+ <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="standard"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e0" source="n0::n3" 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="line" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e1" source="n0::n0" target="n0::n3">
+ <data key="d10">
+ <y:PolyLineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+ <y:Point x="692.5" y="405.9014449999999"/>
+ </y:Path>
+ <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e2" source="n0::n1" target="n0::n3">
+ <data key="d10">
+ <y:PolyLineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+ <y:Point x="790.189453125" y="414.7014449999999"/>
+ </y:Path>
+ <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e3" source="n0::n3" target="n0::n2">
+ <data key="d10">
+ <y:PolyLineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+ <y:Point x="913.0222849999996" y="330.68465576171894"/>
+ <y:Point x="913.0222849999996" y="203.0"/>
+ </y:Path>
+ <y:LineStyle color="#000000" type="line" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ <y:BendStyle smoothed="false"/>
+ </y:PolyLineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e4" source="n0::n4" target="n0::n2">
+ <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="standard"/>
+ <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 7ebcaa2..50b46cb 100644
--- a/documentation/Concepts/interpretation.xml
+++ b/documentation/Concepts/interpretation.xml
@@ -1,415 +1,638 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Interpretation</title>
+ <?xxe-sn 26cy4nalqsw pu35zrt1aby9?>
- <para>Interpretation is mode in which Xreate <emphasis>interprets</emphasis>
- given program i.e. evaluates, expands and simplifies parts of program based
- on information if any known at compilation time. On another hand,
- Interpretation is a middle man or intermediate level between Transcend and
- Brute levels, it facilitates communication between them by means of
- interpreting data of respective layers. It can be further divided into Upper
- and Lower Interpretations depending on interacting with which layer we are
- focused at the moment.</para>
+ <title><?xxe-sn 26cy4nalqsw pu35zrt1abya?>Interpretation</title>
- <programlisting>main= function:: int; entry
+ <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.
+ x= "a":: string.
- y= if (x=="b")::string; i12n(on)
- {1} else {0}.
- y
-}
-</programlisting>
+ y= if (x=="b"):: string; i12n(on)
+ {1} else {0}.
+ y
+}</programlisting>
- <para>In this example, identifier <code>y</code> has annotation
- <code>i12(on)</code> which indicates that compiler should use compile-time
- interpretation to evaluate <code>y</code>. After simplification, the
- function's result is <code>0</code> with neither memory allocations for
- string variable <code>x</code> nor any computation at runtime.</para>
+ <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>
- <para>There are two annotations reserved to control interpretation
- process:</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>
- <para><code>i12n(on)</code> Forces compiler to interpret annotated
- expression, function, function argument. It yields error if expression
- impossible to interpret</para>
+ <?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>
- <para><code>i12n(off)</code> Disables interpretation for annotated
- expression</para>
+ <?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>
- <title>Eligible Expressions</title>
+ <?xxe-sn 26cy4nalqsw pu35zrt1abys?>
+
+ <title><?xxe-sn 26cy4nalqsw pu35zrt1abyt?>Eligible Expressions</title>
- <para>Currently compiler able to interpret following expressions:</para>
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1abyu?>Currently the compiler is able to
+ interpret the following expressions:</para>
<itemizedlist>
+ <?xxe-sn 26cy4nalqsw pu35zrt1abyv?>
+
<listitem>
- <para>Atomic instructions: numbers, strings, identifiers</para>
+ <?xxe-sn 26cy4nalqsw pu35zrt1abyw?>
+
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1abyx?>Atomic instructions: numbers,
+ strings, identifiers.</para>
</listitem>
<listitem>
- <para>Relational and logic operators e.g. <code>x==true</code>,
- <code>x!=0</code></para>
+ <?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>
- <para><code>if</code>, <code>switch</code> statements.
- [[#expansion|Statement expansion]] allowed</para>
+ <?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>
- <para>loop statements. [[#expansion|Statement expansion]]
- allowed</para>
+ <?xxe-sn 26cy4nalqsw pu35zrt1abz6?>
+
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1abz7?>Loop statements.
+ [[#late-interpretation-or-e|Statement expansion]] allowed.</para>
</listitem>
<listitem>
- <para>Functions. [[#function-call-interpreta|Function calls]],
- [[#partial-function|Partial function call interpretation]]</para>
+ <?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>
- <para>index operator e.g. <code>x= {1, 2, 3}. y= x[0]</code>,
- <code>info= {planet="Earth"}. x= info["planet"].</code></para>
+ <?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>
- <para>list operators e.g. <code>x= [1..10]. y={"day",
- "night"}.</code></para>
+ <?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>
- <title>Function Interpretation</title>
+ <?xxe-sn 26cy4nalqsw pu35zrt1abzh?>
- <para>Whole function body could be subject to interpretation if it only
- consists of interpretable expressions.</para>
+ <title><?xxe-sn 26cy4nalqsw pu35zrt1abzi?>Function Interpretation</title>
- <programlisting>unwrap = function(data::unknType, keys::unknType):: unknType; i12n(on)
+ <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]
- }
+ loop fold(keys-&gt;key::string, data-&gt;record):: unknType
+ {
+ record[key]
+ }
}
-test = function:: bool; entry
+test = function:: bool; entry
{
- book = unwrap({
- Library = {
- Shelf = {
- Book = "Aristotle's Politics"
- }}}, {"Library", "Shelf", "Book"}):: unknType.
+ book = unwrap({
+ Library = {
+ Shelf = {
+ Book = "Aristotle's Politics"
+ }}}, {"Library", "Shelf", "Book"}):: unknType.
- book == "Aristotle's Politics"
-}
-</programlisting>
+ book == "Aristotle's Politics"
+}</programlisting>
- <para>The example demonstrates function <code>unwrap</code> which is
- intended to be fully interpretable as depicted by function header
- annotation. Obviously, the interpretable function requires all its
- arguments be also interpretable. In this case compiler able to calculate
- function's result at compile time and nothing of function's body goes to
- compiled code. Compiled code looks like(which also optimized out during
- consequent compilation phases):</para>
+ <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>test = function:: bool; entry
+ <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.
+ book = "Aristotle's Politics":: string; i12n(on).
book == "Aristotle's Politics"
}</programlisting>
- <para>The example also reveals number of similarities with a dynamically
- typed programming languages:</para>
+ <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>
- <para><emphasis>Relaxed types</emphasis>. Notice <code>unknType</code>
- type which has not been defined. It's interpreted well because
- compiler does not look at type system at all since everything can be
- checked at compile time anyway. Interpretation mode is exactly level
- where relaxed type system is possible without any penalties during
- runtime.</para>
+ <?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>
- <para><emphasis>Introspection abilities</emphasis>. Notice how it's
- allowed to treat list fields as string keys, so functions like
- <code>unwrap</code> can get list field name as a parameter. If list
- does not have requested field it just leads to a compilation error and
- no hard to catch runtime bugs.</para>
+ <?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>
- <para>Additional reason for an arbitrary undefined type
- <code>unknType</code> being used in the example is to ensure that no
- compilation occurs and everything done on purely interpretation
- level</para>
+ <?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>In simple cases Interpretation Analysis could determine that
- function is subject to interpretation with no annotation hints
- provided.</para>
-
- <programlisting> 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 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>The only difference from example above is lack of annotation hint
- for <code>unwrap</code>. Developer requires interpretation of
- <code>book</code> variable which in its turn depends on
- <code>unwrap</code>. In this case Analysis able to recognize
- <code>unwrap</code> is possible to interpret, so no errors occur.</para>
+ <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>
- <para>There are, however, more complicated cases for Interpretation
- Analysis:</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>
- <para>Direct recursion. Interpretation Analysis is able to correctly
- find out whether function involving direct recursion(in which a
- function calls itself) is subject to interpretation</para>
+ <?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>
- <para>Indirect recursion. As of now for processing of indirect
- recursion(in which a function is called not by itself but by another
- function) analysis usually fails and rely on manually provided
- annotation hints</para>
+ <?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>Below is an example of a direct recursion:</para>
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1ac0e?>Below is an example of a direct
+ recursion:</para>
- <programlisting>unwrap = function(data:: X):: bool
+ <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])}
+ if (data[0] == "the-end"):: bool
+ {true} else {unwrap(data[0])}
}
-entry = function:: bool; entry {
- unwrap({{{{"the-end"}}}}):: bool; i12n(on)
+entry = function:: bool; entry
+{
+ unwrap({{{{"the-end"}}}}):: bool; i12n(on)
}</programlisting>
- <para>Function <code>unwrap</code> unwraps nested list until it finds
- desired value. No function level annotation required.</para>
+ <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>
- <title>Expansion or Late Interpretation</title>
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac0i?>
- <para>Expansion is a partial simplification or elimination of
- interpretable parts of certain statements.</para>
+ <title><?xxe-sn 26cy4nalqsw pu35zrt1ac0j?>Late Interpretation or
+ Expansion</title>
- <programlisting>test = function(x:: int):: int; entry {
- comm= "inc":: string; i12n(on).
+ <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>
- y= if (comm == "inc"):: int
- {x + 1} else {x}.
- y
-}
-</programlisting>
+ <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).
- <para>In this example, computation of <code>y</code> depends on
- <code>comm</code> and <code>x</code>. On one side, <code>comm</code> has
- an annotation that requires interpretation, on another side <code>x</code>
- is unknown at compile-time and can't be interpreted. In this case the only
- way to satisfy contradictory requirements is to
- <emphasis>expand</emphasis> <code>IF</code> statement, since there is a
- possibility to only interpret condition part of the statement, leaving
- conditional blocks unchanged. In another words, <code>IF</code> statement
- is <emphasis>expanded</emphasis> and just one of the child blocks is
- compiled , <code>x+1</code> in this example based on already known fact
- that the other block would never be executed.</para>
-
- <para>With regard to the fact that expansion leaves some code for
- compilation which has to be executed later as opposed to the "pure
- interpretation" it can be also called <emphasis>late
- interpretation</emphasis> as having runtime footprint.</para>
-
- <para>Below more complex example of a loop expansion:</para>
-
- <programlisting>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>
+ y= if (comm == "inc"):: int
+ {x + 1} else {x}.
+ y
+}</programlisting>
- <para><code>commands</code> contains list of operations that should be
- interpreted as indicated by corresponding annotation. Operand
- <code>x</code> gets assigned at runtime. This is the same situation as in
- previous example and triggers expansion as expected. Result after
- expansion looks as follows:</para>
-
- <programlisting>main = function(x:: int):: int; entry {
- x{1} = x + 1.
- x{2} = x{1} * 2.
- x{3} = x{2} - 1.
- x{3}
+ <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>In other words, this mimics well known loop unrolling technique by
- putting several copies of the loop body in a row, each one for every item
- of a list of `commands`.</para>
+ <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>As of now follow statements support late interpretation:</para>
+ <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>
- <para>Branching statements: <code>if</code>, <code>switch</code>,
- <code>switch variant</code>, <code>switch late</code></para>
+ <?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>
- <para>Loop statements: <code>loop fold</code></para>
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac1e?>
+
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1ac1f?>Loop statements:
+ <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1g?>loop fold</code>.</para>
</listitem>
<listitem>
- <para>functions</para>
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac1h?>
+
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1ac1i?>Functions.</para>
</listitem>
<listitem>
- <para>Other operators: <code>query late</code></para>
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac1j?>
+
+ <para><?xxe-sn 26cy4nalqsw pu35zrt1ac1k?>Other operators:
+ <code><?xxe-sn 26cy4nalqsw pu35zrt1ac1l?>query late</code>.</para>
</listitem>
</itemizedlist>
</section>
<section>
- <title>Partial or Late Function Interpretation</title>
-
- <para>Xreate supports case when function has mixed arguments in regard to
- interpretation, some should be interpreted, while others -
- compiled.</para>
-
- <programlisting>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}
-}
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac1m?>
-main = function(init::int):: int; entry {
- commands= {"inc", "double", "dec"}:: [string]; i12n(on).
+ <title><?xxe-sn 26cy4nalqsw pu35zrt1ac1n?>Partial or Late Function
+ Interpretation</title>
- loop fold(commands-&gt;comm::string, init-&gt;operand):: int
- {
- evaluate(operand, comm)
- }
-}
-</programlisting>
+ <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>
- <para>Looking at function <code>evaluate</code>'s signature in this
- example we can see only one argument <code>code</code> requires
- interpretation. This means that function <code>evaluate</code> is subject
- to a partial interpretation or in other words <emphasis>late function
- interpretation</emphasis>. To enable late interpretation for function at
- least one of its arguments should be annotated as <code>i12n(on)</code>.
- What compiler does next is to generate number of distinctive
- <emphasis>function specializations</emphasis>. Each unique combination of
- interpretable argument values corresponds to its own function
- specialization. This should be used with cautiousness for compiler can
- generate a lot of code for some cases.</para>
-
- <para>Example above generates three different <code>evaluate</code>
- specializations as follows</para>
-
- <programlisting>evaluate1= function(argument:: num):: num {
- argument + 1
+ <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}
}
-evaluate2= function(argument:: num):: num {
- argument * 2
-}
+main = function(init::int):: int; entry
+{
+ commands= {"inc", "double", "dec"}:: [string]; i12n(on).
-evaluate3= function(argument:: num):: num {
- argument - 1
-}
+ loop fold(commands-&gt;comm::string, init-&gt;operand):: int
+ {
+ evaluate(operand, comm)
+ }
+}</programlisting>
-main= function(init::int):: int; entry {
- operand= init:: int.
-
- operand{1}= evaluate1(operand).
- operand{2}= evaluate2(operand(1)).
- operand{3}= evaluate3(operand(2)).
-
- operand(3)
-}
-</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>
- <title>Domain Specific Languages and Interpretation</title>
-
- <para>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>queries</emphasis> and <emphasis>configs</emphasis>, to name a
- few. It is possible to use interpretation abilities to emulate DSL.
- Developer can express desired functionality as a nested lists of numbers,
- variants and strings which then processed by partially interpreted
- function. Such function in its turn transforms input data into set of low
- level compilation instructions so there is no runtime overhead.</para>
+ <?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>
- <title>On Interpretation Analysis</title>
+ <?xxe-sn 26cy4nalqsw pu35zrt1ac25?>
- <para>Analysis follows classical type reconstruction algorithms to
- determine which expressions are subject to an interpretation and check
- correctness of reconstruction w.r.t. developer-provided annotations.
- Analysis consists of two general parts:</para>
+ <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>
- <para><emphasis>Inference</emphasis>. Infers is it possible to
- interpret expression based on known decisions for its arguments</para>
+ <?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>
- <para><emphasis>Unification</emphasis>. Assigns appropriate decision
- w.r.t. to a previously inferred expectations and developer-provided
- hints as well</para>
+ <?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
+#6 2018-12-15T16:59:22Z pgess
+#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/Concepts/polymorphism.xml b/documentation/Concepts/polymorphism.xml
index d1e0674..c453c27 100644
--- a/documentation/Concepts/polymorphism.xml
+++ b/documentation/Concepts/polymorphism.xml
@@ -1,182 +1,224 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Polymorphism</title>
+ <?xxe-sn 26n42fz1reo 1?>
- <para><emphasis>Polymorphism</emphasis> is an umbrella term to denote number
- of techniques across different programing paradigms. They all share the same
- intention to provide ability easily recombine software components in a
- different way with as little as possible manual work on developer's side. It
- serves two major goals: <emphasis>specialization</emphasis>, when software,
+ <title><?xxe-sn 26n42fz1reo 2?>Polymorphism</title>
+
+ <para><?xxe-sn 26n42fz1reo 3?><emphasis><?xxe-sn 26n42fz1reo 4?>Polymorphism</emphasis>
+ is an umbrella term to denote number of techniques across different
+ programing paradigms. They all share the same intention to provide ability
+ easily recombine software components in a different way with as little as
+ possible manual work on developer's side. It serves two major goals:
+ <emphasis><?xxe-sn 26n42fz1reo 5?>specialization</emphasis>, when software,
initially designed to support wide range of use cases, is configured for
- concrete particular case and <emphasis>extension</emphasis> - adapting
- software to an environment and conditions it was not specifically designed
- for.</para>
+ concrete particular case and <emphasis><?xxe-sn 26n42fz1reo 6?>extension</emphasis>
+ - adapting software to an environment and conditions it was not specifically
+ designed for.</para>
- <para>In course of software engineering evolution, number of polymorphism
- techniques was proposed and experimented with, all suited for different
- use-cases. Xreate presents generalized and elegant approach that
- exhaustively covers wide landscape of polymorphism variations.</para>
+ <para><?xxe-sn 26n42fz1reo 7?>In course of software engineering evolution,
+ number of polymorphism techniques was proposed and experimented with, all
+ suited for different use-cases. Xreate presents generalized and elegant
+ approach that exhaustively covers wide landscape of polymorphism
+ variations.</para>
- <para>Polymorphism in Xreate can be applied on two levels:</para>
+ <para><?xxe-sn 26n42fz1reo 8?>Polymorphism in Xreate can be applied on two
+ levels:</para>
<itemizedlist>
+ <?xxe-sn 26n42fz1reo 9?>
+
<listitem>
- <para><emphasis>Functions level</emphasis>. Function in Xreate can have
- a multiple <emphasis>specializations</emphasis> and polymorphism is
- compiler's ability to decide which exactly specialization to use
- depending on various factors</para>
+ <?xxe-sn 26n42fz1reo a?>
+
+ <para><?xxe-sn 26n42fz1reo b?><emphasis><?xxe-sn 26n42fz1reo c?>Functions
+ level</emphasis>. Function in Xreate can have a multiple
+ <emphasis><?xxe-sn 26n42fz1reo d?>specializations</emphasis> and
+ polymorphism is compiler's ability to decide which exactly
+ specialization to use depending on various factors</para>
</listitem>
<listitem>
- <para><emphasis>Modules level</emphasis>. Multiple modules can provide
- the same service for users. <link
- xlink:href="/w/syntax/modules/#modules-resolution">Modules
+ <?xxe-sn 26n42fz1reo e?>
+
+ <para><?xxe-sn 26n42fz1reo f?><emphasis><?xxe-sn 26n42fz1reo g?>Modules
+ level</emphasis>. Multiple modules can provide the same service for
+ users. <link
+ xlink:href="/w/syntax/modules/#modules-resolution"><?xxe-sn 26n42fz1reo h?>Modules
Resolution</link> is a process to decide which exactly module to
use</para>
</listitem>
</itemizedlist>
<section>
- <title>Function Level Polymorphism</title>
-
- <para>Basic idea is to allow developer to define several functions with
- the same name or, in other words, several
- <emphasis>specializations</emphasis>. Caller code then invokes necessary
- function by its shared name but can't directly specify particular
- specialization. Exact specialization to be invoked is decided later by
- decision process called <emphasis>polymorphism resolution</emphasis>
- carried out by Transcend. This indirect invocation approach gives enough
- flexibility to use or replace different specializations depending on
- various conditions during compile time as well as at runtime.</para>
-
- <para>Please refer to <link
- xlink:href="/w/syntax#function-specializations">syntax</link> for details
- about function specializations. Each specialization must have unique
- <emphasis>guard</emphasis>(among all specializations with the same name)
- to be discernible from others. To summarize, function invocation is a two
- layered process, in which client code specifies callee function's shared
- name, and polymorphism resolution specifies specialization guard if
- needed.</para>
-
- <para>For an example, assume that we develop program to operate under
- specified time constraints. To model implementation suitable for real time
- environment, one specialization of <code>crucialOperation</code> is
- defined with <code>env(realtime)</code> guard i.e. satisfies some fixed
- execution time constraints. Caller <code>main</code> specifies only
- function name <code>crucialOperation</code> thus delegating decision on
- guard to a polymorphism resolution done elsewhere, based on environment's
- constraints the code is executed in.</para>
-
- <programlisting xml:id="FnLvlPoly_1">guard:: env(realtime)
+ <?xxe-sn 26n42fz1reo i?>
+
+ <title><?xxe-sn 26n42fz1reo j?>Function Level Polymorphism</title>
+
+ <para><?xxe-sn 26n42fz1reo k?>Basic idea is to allow developer to define
+ several functions with the same name or, in other words, several
+ <emphasis><?xxe-sn 26n42fz1reo l?>specializations</emphasis>. Caller code
+ then invokes necessary function by its shared name but can't directly
+ specify particular specialization. Exact specialization to be invoked is
+ decided later by decision process called <emphasis><?xxe-sn 26n42fz1reo m?>polymorphism
+ resolution</emphasis> carried out by Transcend. This indirect invocation
+ approach gives enough flexibility to use or replace different
+ specializations depending on various conditions during compile time as
+ well as at runtime.</para>
+
+ <para><?xxe-sn 26n42fz1reo n?>Please refer to <link
+ xlink:href="/w/syntax#function-specializations"><?xxe-sn 26n42fz1reo o?>syntax</link>
+ for details about function specializations. Each specialization must have
+ unique <emphasis><?xxe-sn 26n42fz1reo p?>guard</emphasis>(among all
+ specializations with the same name) to be discernible from others. To
+ summarize, function invocation is a two layered process, in which client
+ code specifies callee function's shared name, and polymorphism resolution
+ specifies specialization guard if needed.</para>
+
+ <para><?xxe-sn 26n42fz1reo q?>For an example, assume that we develop
+ program to operate under specified time constraints. To model
+ implementation suitable for real time environment, one specialization of
+ <code><?xxe-sn 26n42fz1reo r?>crucialOperation</code> is defined with
+ <code><?xxe-sn 26n42fz1reo s?>env(realtime)</code> guard i.e. satisfies
+ some fixed execution time constraints. Caller <code><?xxe-sn 26n42fz1reo t?>main</code>
+ specifies only function name <code><?xxe-sn 26n42fz1reo u?>crucialOperation</code>
+ thus delegating decision on guard to a polymorphism resolution done
+ elsewhere, based on environment's constraints the code is executed
+ in.</para>
+
+ <programlisting xml:id="FnLvlPoly_1"><?xxe-sn 26n42fz1reo v?>guard:: env(realtime)
{
crucialOperation = function:: int
{ 0 }
}
main = function:: int; entry
{
crucialOperation()
} </programlisting>
</section>
<section>
- <title>Polymorphism Resolution</title>
+ <?xxe-sn 26n42fz1reo w?>
+
+ <title><?xxe-sn 26n42fz1reo x?>Polymorphism Resolution</title>
- <synopsis>SYNTAX:
+ <synopsis><?xxe-sn 26n42fz1reo y?>SYNTAX:
**dfa_callguard**(//call-site-ref//, //guard//)</synopsis>
<itemizedlist>
+ <?xxe-sn 26n42fz1reo z?>
+
<listitem>
- <para><emphasis>call-site-ref</emphasis> reference to a call site in
- AST</para>
+ <?xxe-sn 26n42fz1reo 10?>
+
+ <para><?xxe-sn 26n42fz1reo 11?><emphasis><?xxe-sn 26n42fz1reo 12?>call-site-ref</emphasis>
+ reference to a call site in AST</para>
</listitem>
<listitem>
- <para><emphasis>guard</emphasis> resolved function specialization
- guard</para>
+ <?xxe-sn 26n42fz1reo 13?>
+
+ <para><?xxe-sn 26n42fz1reo 14?><emphasis><?xxe-sn 26n42fz1reo 15?>guard</emphasis>
+ resolved function specialization guard</para>
</listitem>
</itemizedlist>
- <para>When compiler encounters function invocation that has several
- specialization it refers to the table <code>dfa_callguard</code> to find
- out which specialization to call. It must have entry with appropriate
- <code>guard</code> for every invocation site <code>call-site-ref</code> of
- a polymorphic function. Polymorphism resolution is a process of filling
- out <code>dfa_callguard</code> for a compiler based on custom Transcend
- rules reflecting one or another polymorphism strategy.</para>
+ <para><?xxe-sn 26n42fz1reo 16?>When compiler encounters function
+ invocation that has several specialization it refers to the table
+ <code><?xxe-sn 26n42fz1reo 17?>dfa_callguard</code> to find out which
+ specialization to call. It must have entry with appropriate
+ <code><?xxe-sn 26n42fz1reo 18?>guard</code> for every invocation site
+ <code><?xxe-sn 26n42fz1reo 19?>call-site-ref</code> of a polymorphic
+ function. Polymorphism resolution is a process of filling out
+ <code><?xxe-sn 26n42fz1reo 1a?>dfa_callguard</code> for a compiler based
+ on custom Transcend rules reflecting one or another polymorphism
+ strategy.</para>
</section>
<section>
- <title>Late Polymorphism</title>
+ <?xxe-sn 26n42fz1reo 1b?>
+
+ <title><?xxe-sn 26n42fz1reo 1c?>Late Polymorphism</title>
- <para>Late Polymorphism is an extension to allow polymorphism resolution
- to be based on data known only at runtime, i.e. resolve function
- specializations dynamically. The Idea is to use Late Transcend to access
- runtime data. See <link xlink:href="/w/transcend/latetranscend">Late
+ <para><?xxe-sn 26n42fz1reo 1d?>Late Polymorphism is an extension to allow
+ polymorphism resolution to be based on data known only at runtime, i.e.
+ resolve function specializations dynamically. The Idea is to use Late
+ Transcend to access runtime data. See <link
+ xlink:href="/w/transcend/latetranscend"><?xxe-sn 26n42fz1reo 1e?>Late
Transcend</link> for details.</para>
- <para>Example below demonstrates <code>test</code> invoking polymorphic
- function <code>compute</code>:</para>
+ <para><?xxe-sn 26n42fz1reo 1f?>Example below demonstrates <code><?xxe-sn 26n42fz1reo 1g?>test</code>
+ invoking polymorphic function <code><?xxe-sn 26n42fz1reo 1h?>compute</code>:</para>
- <programlisting xml:id="LatePoly_1">Strategy = type variant {fast, precise}.
+ <programlisting xml:id="LatePoly_1"><?xxe-sn 26n42fz1reo 1i?>Strategy = type variant {fast, precise}.
guard:: fast
{
compute = function:: int
{0}
}
guard:: precise
{
compute = function:: int
{1}
}
test = function(s:: Strategy; alias(strategy)):: int; entry
{
switch late (s):: int
{
compute():: int; guardalias(strategy)
}
}</programlisting>
- <para>Function <code>compute</code> has two specializations,
- <code>fast</code> and <code>precise</code>. We see that <code>test</code>
- gets parameter <code>s</code> that dictates exact strategy to use.
- Clearly, resolution should work dynamically to cope with cases like this,
- for value of parameter <code>s</code> not only is unknown at compile time,
- but it can change with each <code>test</code> execution.</para>
-
- <para>Operation Switch Late is compiled into several branches, two in this
- case, each branch executing appropriate <code>compute</code>
- specialization. Correct branch executed depending on current
- <code>s</code> value. Custom annotations <code>alias(Alias)</code> and
- <code>guardalias(Alias)</code> used to assign an alias in order to specify
- which parameter to use for as basis for resolution</para>
+ <para><?xxe-sn 26n42fz1reo 1j?>Function <code><?xxe-sn 26n42fz1reo 1k?>compute</code>
+ has two specializations, <code><?xxe-sn 26n42fz1reo 1l?>fast</code> and
+ <code><?xxe-sn 26n42fz1reo 1m?>precise</code>. We see that <code><?xxe-sn 26n42fz1reo 1n?>test</code>
+ gets parameter <code><?xxe-sn 26n42fz1reo 1o?>s</code> that dictates exact
+ strategy to use. Clearly, resolution should work dynamically to cope with
+ cases like this, for value of parameter <code><?xxe-sn 26n42fz1reo 1p?>s</code>
+ not only is unknown at compile time, but it can change with each
+ <code><?xxe-sn 26n42fz1reo 1q?>test</code> execution.</para>
+
+ <para><?xxe-sn 26n42fz1reo 1r?>Operation Switch Late is compiled into
+ several branches, two in this case, each branch executing appropriate
+ <code><?xxe-sn 26n42fz1reo 1s?>compute</code> specialization. Correct
+ branch executed depending on current <code><?xxe-sn 26n42fz1reo 1t?>s</code>
+ value. Custom annotations <code><?xxe-sn 26n42fz1reo 1u?>alias(Alias)</code>
+ and <code><?xxe-sn 26n42fz1reo 1v?>guardalias(Alias)</code> used to assign
+ an alias in order to specify which parameter to use for as basis for
+ resolution</para>
</section>
<section>
- <title>Auto Expansion of Late Parameters</title>
-
- <para>In previous example, switch late operation was used to facilitate
- calling of polymorphic function with late polymorphism resolution. It's
- not that convenient to wrap each invocation by switch late whenever there
- is need to call late polymorphic function. Specifically to handle cases
- like this, compiler uses late parameter auto expansion technique.</para>
-
- <para>If compiler discovers that <code>late(dfa_callguard())</code> entry
- exists for current invocation and it does not have enclosing switch late
- already, compiler automatically generates different branches that invoke
- relevant specializations and transfers control to a branch depending on
- late parameter value. In other words invocation implicitly wrapped into
- switch late instruction if needed.</para>
+ <?xxe-sn 26n42fz1reo 1w?>
+
+ <title><?xxe-sn 26n42fz1reo 1x?>Auto Expansion of Late Parameters</title>
+
+ <para><?xxe-sn 26n42fz1reo 1y?>In previous example, switch late operation
+ was used to facilitate calling of polymorphic function with late
+ polymorphism resolution. It's not that convenient to wrap each invocation
+ by switch late whenever there is need to call late polymorphic function.
+ Specifically to handle cases like this, compiler uses late parameter auto
+ expansion technique.</para>
+
+ <para><?xxe-sn 26n42fz1reo 1z?>If compiler discovers that <code><?xxe-sn 26n42fz1reo 20?>late(dfa_callguard())</code>
+ entry exists for current invocation and it does not have enclosing switch
+ late already, compiler automatically generates different branches that
+ invoke relevant specializations and transfers control to a branch
+ depending on late parameter value. In other words invocation implicitly
+ wrapped into switch late instruction if needed.</para>
</section>
</chapter>
+<?xxe-revisions
+#1 2018-12-12T21:49:13Z pgess
+?>
\ No newline at end of file
diff --git a/documentation/Syntax/modules.xml b/documentation/Syntax/modules.xml
index cf61944..c08f132 100644
--- a/documentation/Syntax/modules.xml
+++ b/documentation/Syntax/modules.xml
@@ -1,262 +1,325 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Modules</title>
-
- <para>Xreate offers <emphasis>modules</emphasis> as a way to organize and
- reuse source code. For simplicity, it's implemented as one file—one
- module.</para>
-
- <para>Modules often require prior compilation of other modules for correct
- work. It leads to a problem of a <emphasis>resolution</emphasis> where
- required module is located. Especially since modern software products
- usually have complicated and volatile file structure depending on exact
- configuration and platform to build. Common practice is to rely on build
- configuration tools to provide exact path for each module.</para>
-
- <para>For this reason Xreate interferes as little as possible with
- resolution. Language does not support for module to directly specify any
- path be it relative or absolute of other required modules. Also compiler
- does not search modules in some predefined list of directories and does not
- assume anything about project's file structure. It expects resolution
- information already fully defined before compilation.</para>
-
- <para>However compiler has optional built-in functionality to facilitate
- resolution. It is the very kind of problems the transcend level suited
- excellently for. It is modeled as <emphasis>supply and demand</emphasis>
- approach and lets modules to declare what they <emphasis>provide</emphasis>
- and what <emphasis>require</emphasis> expressed by annotations. Compiler
- then tries to satisfy requirements and find a match. Alternatively, external
- tools always can be used.</para>
+ <?xxe-sn 26n42fz1reo 21?>
+
+ <title><?xxe-sn 26n42fz1reo 22?>Modules</title>
+
+ <para><?xxe-sn 26n42fz1reo 23?>Xreate offers <emphasis><?xxe-sn 26n42fz1reo 24?>modules</emphasis>
+ as a way to organize and reuse source code. For simplicity, it's implemented
+ as one file—one module.</para>
+
+ <para><?xxe-sn 26n42fz1reo 25?>Modules often require prior compilation of
+ other modules for correct work. It leads to a problem of a
+ <emphasis><?xxe-sn 26n42fz1reo 26?>resolution</emphasis> where required
+ module is located. Especially since modern software products usually have
+ complicated and volatile file structure depending on exact configuration and
+ platform to build. Common practice is to rely on build configuration tools
+ to provide exact path for each module.</para>
+
+ <para><?xxe-sn 26n42fz1reo 27?>For this reason Xreate interferes as little
+ as possible with resolution. Language does not support for module to
+ directly specify any path be it relative or absolute of other required
+ modules. Also compiler does not search modules in some predefined list of
+ directories and does not assume anything about project's file structure. It
+ expects resolution information already fully defined before
+ compilation.</para>
+
+ <para><?xxe-sn 26n42fz1reo 28?>However compiler has optional built-in
+ functionality to facilitate resolution. It is the very kind of problems the
+ transcend level suited excellently for. It is modeled as <emphasis><?xxe-sn 26n42fz1reo 29?>supply
+ and demand</emphasis> approach and lets modules to declare what they
+ <emphasis><?xxe-sn 26n42fz1reo 2a?>provide</emphasis> and what
+ <emphasis><?xxe-sn 26n42fz1reo 2b?>require</emphasis> expressed by
+ annotations. Compiler then tries to satisfy requirements and find a match.
+ Alternatively, external tools always can be used.</para>
<section>
- <title>Module Headers</title>
+ <?xxe-sn 26n42fz1reo 2c?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 26n42fz1reo 2d?>Module Headers</title>
+
+ <synopsis><?xxe-sn 26n42fz1reo 2e?>SYNTAX:
**module** [:: //annotations-list// ] (Full form)
{
//module-statement//...
}</synopsis>
- <synopsis>**module** :: //annotations-list// . (Simplified form)</synopsis>
+ <synopsis><?xxe-sn 26n42fz1reo 2f?>**module** :: //annotations-list// . (Simplified form)</synopsis>
- <synopsis>//module-statement// ::=
+ <synopsis><?xxe-sn 26n42fz1reo 2g?>//module-statement// ::=
| **require** ( //annotation// ). (1)
| **discover** ( //path// ). (2)
| **controller** (//path//). (3)</synopsis>
<itemizedlist>
+ <?xxe-sn 26n42fz1reo 2h?>
+
<listitem>
- <para><code>annotations-list</code> List of annotations delimited by
- semicolon</para>
+ <?xxe-sn 26n42fz1reo 2i?>
+
+ <para><?xxe-sn 26n42fz1reo 2j?><code><?xxe-sn 26n42fz1reo 2k?>annotations-list</code>
+ List of annotations delimited by semicolon</para>
</listitem>
<listitem>
- <para><code>annotation</code> Any valid transcend expression</para>
+ <?xxe-sn 26n42fz1reo 2l?>
+
+ <para><?xxe-sn 26n42fz1reo 2m?><code><?xxe-sn 26n42fz1reo 2n?>annotation</code>
+ Any valid transcend expression</para>
</listitem>
<listitem>
- <para><code>path</code> Absolute or relative path to controller</para>
+ <?xxe-sn 26n42fz1reo 2o?>
+
+ <para><?xxe-sn 26n42fz1reo 2p?><code><?xxe-sn 26n42fz1reo 2q?>path</code>
+ Absolute or relative path to controller</para>
</listitem>
</itemizedlist>
- <para>Xreate recognizes number of module management statements. Those
- statements should be located in specific section <code>module {...}</code>
- of a source code which is called <emphasis>module header</emphasis>.
- Module can have several headers. All headers gathered from a whole file
- are combined into one before actual processing.</para>
+ <para><?xxe-sn 26n42fz1reo 2r?>Xreate recognizes number of module
+ management statements. Those statements should be located in specific
+ section <code><?xxe-sn 26n42fz1reo 2s?>module {...}</code> of a source
+ code which is called <emphasis><?xxe-sn 26n42fz1reo 2t?>module
+ header</emphasis>. Module can have several headers. All headers gathered
+ from a whole file are combined into one before actual processing.</para>
<note>
- <para>Modules processing happens before compilation. It means any data
- produced in course of compilation is inaccessible at this stage</para>
+ <?xxe-sn 26n42fz1reo 2u?>
+
+ <para><?xxe-sn 26n42fz1reo 2v?>Modules processing happens before
+ compilation. It means any data produced in course of compilation is
+ inaccessible at this stage</para>
</note>
</section>
<section>
- <title>Requesting Modules</title>
+ <?xxe-sn 26n42fz1reo 2w?>
+
+ <title><?xxe-sn 26n42fz1reo 2x?>Requesting Modules</title>
- <para>Statement <code>require(..)</code> expresses which modules are
- required for correct compilation.</para>
+ <para><?xxe-sn 26n42fz1reo 2y?>Statement <code><?xxe-sn 26n42fz1reo 2z?>require(..)</code>
+ expresses which modules are required for correct compilation.</para>
- <programlisting xml:id="Requesting_Modules_1">module {
+ <programlisting xml:id="Requesting_Modules_1"><?xxe-sn 26n42fz1reo 30?>module {
require(logger).
}</programlisting>
- <para>In this example module in question requires some other module that
- <emphasis>provides</emphasis> feature called <code>logger</code>. There is
- no way to specify direct external module location. Instead, module
- expresses requirement in abstract form as propositional expression which
- is later used by resolution to find exact match.</para>
+ <para><?xxe-sn 26n42fz1reo 31?>In this example module in question requires
+ some other module that <emphasis><?xxe-sn 26n42fz1reo 32?>provides</emphasis>
+ feature called <code><?xxe-sn 26n42fz1reo 33?>logger</code>. There is no
+ way to specify direct external module location. Instead, module expresses
+ requirement in abstract form as propositional expression which is later
+ used by resolution to find exact match.</para>
- <programlisting xml:id="Requesting_Modules_2">module{require(stringslib).}
+ <programlisting xml:id="Requesting_Modules_2"><?xxe-sn 26n42fz1reo 34?>module{require(stringslib).}
processString = function(a:: string):: string
{
someStrFunc(a)
}
module{require(mathlib).}
processNumber = function(a:: num):: num
{
someMathFunc(a)
}</programlisting>
- <para>Example above demonstrates using several headers in one file. It's
- particularly useful if developer finds it convenient to put requirements
- near the actual code that uses it. This way it can be easily spotted when
- requirements are no more needed. After all, code locality improves
- readability.</para>
+ <para><?xxe-sn 26n42fz1reo 35?>Example above demonstrates using several
+ headers in one file. It's particularly useful if developer finds it
+ convenient to put requirements near the actual code that uses it. This way
+ it can be easily spotted when requirements are no more needed. After all,
+ code locality improves readability.</para>
</section>
<section>
- <title>Module Annotations</title>
+ <?xxe-sn 26n42fz1reo 36?>
- <para>Module can declare additional information for various uses. This is
- expressed by annotations located in the header. They are called module
- annotations. For instance, module annotations can be used by module
- resolution to find modules that satisfy requirements of others.</para>
+ <title><?xxe-sn 26n42fz1reo 37?>Module Annotations</title>
- <programlisting xml:id="ModuleAnnotations_1">module:: status(obsolete).</programlisting>
+ <para><?xxe-sn 26n42fz1reo 38?>Module can declare additional information
+ for various uses. This is expressed by annotations located in the header.
+ They are called module annotations. For instance, module annotations can
+ be used by module resolution to find modules that satisfy requirements of
+ others.</para>
- <para>The example shows module that declares its status. It can be used by
- resolution to choose most appropriate module out of number of candidates.
- One way to view annotations used by resolution is to treat them as
- something that module <emphasis>provides</emphasis>.</para>
+ <programlisting xml:id="ModuleAnnotations_1"><?xxe-sn 26n42fz1reo 39?>module:: status(obsolete).</programlisting>
+
+ <para><?xxe-sn 26n42fz1reo 3a?>The example shows module that declares its
+ status. It can be used by resolution to choose most appropriate module out
+ of number of candidates. One way to view annotations used by resolution is
+ to treat them as something that module <emphasis><?xxe-sn 26n42fz1reo 3b?>provides</emphasis>.</para>
<note>
- <para>There are no predefined module annotations and developer can put
- arbitrary information there.</para>
+ <?xxe-sn 26n42fz1reo 3c?>
+
+ <para><?xxe-sn 26n42fz1reo 3d?>There are no predefined module
+ annotations and developer can put arbitrary information there.</para>
</note>
</section>
<section>
- <title>Modules Resolution</title>
+ <?xxe-sn 26n42fz1reo 3e?>
- <para>Modules resolution is a process to find exact modules locations that
- match requests. Compiler does not search modules in predefined directories
- and does not assume anything about project's file structure. In order to
- allow developer to determine it themselves the compiler refers to two
- transcend tables</para>
+ <title><?xxe-sn 26n42fz1reo 3f?>Modules Resolution</title>
- <synopsis>SYNTAX:
+ <para><?xxe-sn 26n42fz1reo 3g?>Modules resolution is a process to find
+ exact modules locations that match requests. Compiler does not search
+ modules in predefined directories and does not assume anything about
+ project's file structure. In order to allow developer to determine it
+ themselves the compiler refers to two transcend tables</para>
+
+ <synopsis><?xxe-sn 26n42fz1reo 3h?>SYNTAX:
**modules_resolution**(//request//, //module-resolved//). (1)
**modules_resolution**(//request//, //module-resolved//, //module-context//). (2)</synopsis>
<itemizedlist>
+ <?xxe-sn 26n42fz1reo 3i?>
+
<listitem>
- <para><emphasis>request</emphasis> annotation used in statement
- <code>request(...)</code></para>
+ <?xxe-sn 26n42fz1reo 3j?>
+
+ <para><?xxe-sn 26n42fz1reo 3k?><emphasis><?xxe-sn 26n42fz1reo 3l?>request</emphasis>
+ annotation used in statement <code><?xxe-sn 26n42fz1reo 3m?>request(...)</code></para>
</listitem>
<listitem>
- <para><emphasis>module-resolved</emphasis> Path or identifier of a
- module that matches request</para>
+ <?xxe-sn 26n42fz1reo 3n?>
+
+ <para><?xxe-sn 26n42fz1reo 3o?><emphasis><?xxe-sn 26n42fz1reo 3p?>module-resolved</emphasis>
+ Path or identifier of a module that matches request</para>
</listitem>
<listitem>
- <para><emphasis>module-context</emphasis> Path or identifier of a
- module that requires other module</para>
+ <?xxe-sn 26n42fz1reo 3q?>
+
+ <para><?xxe-sn 26n42fz1reo 3r?><emphasis><?xxe-sn 26n42fz1reo 3s?>module-context</emphasis>
+ Path or identifier of a module that requires other module</para>
</listitem>
</itemizedlist>
- <para>These tables contain resolved modules for all possible requests.
- Form (1) contains requests that should always be resolved to the same
- module. Form (2) contains such requests for which resolution depends on
- requesting module <emphasis>module-context</emphasis>.</para>
+ <para><?xxe-sn 26n42fz1reo 3t?>These tables contain resolved modules for
+ all possible requests. Form (1) contains requests that should always be
+ resolved to the same module. Form (2) contains such requests for which
+ resolution depends on requesting module <emphasis><?xxe-sn 26n42fz1reo 3u?>module-context</emphasis>.</para>
- <programlisting xml:id="ModulesResolution_1"> modules_resolution(numlib, "/path/to/numlib").
+ <programlisting xml:id="ModulesResolution_1"><?xxe-sn 26n42fz1reo 3v?> modules_resolution(numlib, "/path/to/numlib").
modules_resolution(strings, "/path/to/ansi-lib", "moduleA").
modules_resolution(strings, "/path/to/utf8-lib", "moduleB"). </programlisting>
- <para>For the example above the compiler would always resolve path to
- numerical lib(<code>numlib</code>) as "/path/to/numlib" (line 1). However
- <code>strings</code> library would be resolved as "/path/to/ansi-lib" if
- requested in <code>moduleA</code>(line 2) and as "/path/to/utf8-lib" if
- requested in <code>moduleB</code>(line 3).</para>
+ <para><?xxe-sn 26n42fz1reo 3w?>For the example above the compiler would
+ always resolve path to numerical lib(<code><?xxe-sn 26n42fz1reo 3x?>numlib</code>)
+ as "/path/to/numlib" (line 1). However <code><?xxe-sn 26n42fz1reo 3y?>strings</code>
+ library would be resolved as "/path/to/ansi-lib" if requested in
+ <code><?xxe-sn 26n42fz1reo 3z?>moduleA</code>(line 2) and as
+ "/path/to/utf8-lib" if requested in <code><?xxe-sn 26n42fz1reo 40?>moduleB</code>(line
+ 3).</para>
- <para>When compiler encounters module request it looks up table
- <code>modules_resolution</code> (first or second form) to find path of the
- requested module. Tables can be populated by any means be it either
- transcend reasoning or external tools.</para>
+ <para><?xxe-sn 26n42fz1reo 41?>When compiler encounters module request it
+ looks up table <code><?xxe-sn 26n42fz1reo 42?>modules_resolution</code>
+ (first or second form) to find path of the requested module. Tables can be
+ populated by any means be it either transcend reasoning or external
+ tools.</para>
<note>
- <para>There is no defined order or priority or fall back behavior while
- looking into tables. If the same request occurs in both tables they are
- considered to be ill-formed</para>
+ <?xxe-sn 26n42fz1reo 43?>
+
+ <para><?xxe-sn 26n42fz1reo 44?>There is no defined order or priority or
+ fall back behavior while looking into tables. If the same request occurs
+ in both tables they are considered to be ill-formed</para>
</note>
</section>
<section>
- <title>Advanced Modules Resolution</title>
+ <?xxe-sn 26n42fz1reo 45?>
+
+ <title><?xxe-sn 26n42fz1reo 46?>Advanced Modules Resolution</title>
- <para>Xreate provide additional layer, optional helper to simplify modules
- management. It introduces two more built-in statements that can be used in
- module header: <emphasis>Discover</emphasis> statement and
- <emphasis>Controller</emphasis> Statement.</para>
+ <para><?xxe-sn 26n42fz1reo 47?>Xreate provide additional layer, optional
+ helper to simplify modules management. It introduces two more built-in
+ statements that can be used in module header: <emphasis><?xxe-sn 26n42fz1reo 48?>Discover</emphasis>
+ statement and <emphasis><?xxe-sn 26n42fz1reo 49?>Controller</emphasis>
+ Statement.</para>
<itemizedlist>
+ <?xxe-sn 26n42fz1reo 4a?>
+
<listitem>
- <para><emphasis>Discover Statement</emphasis> has the form
- <code>discover (<emphasis>path</emphasis>)</code>.It allows to specify
- directory where compiler would recursively search for all xreate files
- and extract module header annotations. It gathers info about all found
- source files.</para>
+ <?xxe-sn 26n42fz1reo 4b?>
+
+ <para><?xxe-sn 26n42fz1reo 4c?><emphasis><?xxe-sn 26n42fz1reo 4d?>Discover
+ Statement</emphasis> has the form <code><?xxe-sn 26n42fz1reo 4e?>discover
+ (<emphasis><?xxe-sn 26n42fz1reo 4f?>path</emphasis>)</code>.It allows
+ to specify directory where compiler would recursively search for all
+ xreate files and extract module header annotations. It gathers info
+ about all found source files.</para>
</listitem>
<listitem>
- <para><emphasis>Controller Statement</emphasis> has the form
- <code>controller (<emphasis>path</emphasis>)</code> and specifies path
- to modules resolution controller. Controller is a file that contains
- transcend rules in order to process data gathered by discovery and
- populate resolution tables as its result of work.</para>
+ <?xxe-sn 26n42fz1reo 4g?>
+
+ <para><?xxe-sn 26n42fz1reo 4h?><emphasis><?xxe-sn 26n42fz1reo 4i?>Controller
+ Statement</emphasis> has the form <code><?xxe-sn 26n42fz1reo 4j?>controller
+ (<emphasis><?xxe-sn 26n42fz1reo 4k?>path</emphasis>)</code> and
+ specifies path to modules resolution controller. Controller is a file
+ that contains transcend rules in order to process data gathered by
+ discovery and populate resolution tables as its result of work.</para>
</listitem>
</itemizedlist>
- <para>Example below shows 3 modules:</para>
+ <para><?xxe-sn 26n42fz1reo 4l?>Example below shows 3 modules:</para>
- <programlisting xml:id="AdvModRes_1">//First Module
+ <programlisting xml:id="AdvModRes_1"><?xxe-sn 26n42fz1reo 4m?>//First Module
module::
name(testA);
provide(superService);
status(needToTestEvenMore).
//Second Module
module::
name(testB);
provide(superService);
status(needToTest).
//Third Module
module {
require(superService).
discover("/modules/path/").
controller("/path/to/controller").
}</programlisting>
- <para>Two modules offer the same feature
- <code>provide(superSerivce)</code>. Third module requires it and specifies
- directory where to look up for needed files. Controller's task is to
- populate resolution table if needed module is found and choose appropriate
- candidate, if more than one module offer this service.</para>
-
- <para>One way to decide what to choose in this example is to look at
- status of both modules. Let score be assigned to each possible status.
- Let's say <code>0</code> for <code>status(needToTestEvenMore)</code>,
- <code>1</code> for <code>status(needToTest)</code>. Then controller would
- proceed with the best scoring module, <code>Second Module</code> in this
- case.</para>
+ <para><?xxe-sn 26n42fz1reo 4n?>Two modules offer the same feature
+ <code><?xxe-sn 26n42fz1reo 4o?>provide(superSerivce)</code>. Third module
+ requires it and specifies directory where to look up for needed files.
+ Controller's task is to populate resolution table if needed module is
+ found and choose appropriate candidate, if more than one module offer this
+ service.</para>
+
+ <para><?xxe-sn 26n42fz1reo 4p?>One way to decide what to choose in this
+ example is to look at status of both modules. Let score be assigned to
+ each possible status. Let's say <code><?xxe-sn 26n42fz1reo 4q?>0</code>
+ for <code><?xxe-sn 26n42fz1reo 4r?>status(needToTestEvenMore)</code>,
+ <code><?xxe-sn 26n42fz1reo 4s?>1</code> for <code><?xxe-sn 26n42fz1reo 4t?>status(needToTest)</code>.
+ Then controller would proceed with the best scoring module,
+ <code><?xxe-sn 26n42fz1reo 4u?>Second Module</code> in this case.</para>
</section>
<section>
- <title>See Also</title>
+ <?xxe-sn 26n42fz1reo 4v?>
+
+ <title><?xxe-sn 26n42fz1reo 4w?>See Also</title>
- <para>Transcend: <link xlink:href="/w/transcend/modules-api">Modules
+ <para><?xxe-sn 26n42fz1reo 4x?>Transcend: <link
+ xlink:href="/w/transcend/modules-api"><?xxe-sn 26n42fz1reo 4y?>Modules
API</link></para>
</section>
</chapter>
+<?xxe-revisions
+#1 2018-12-12T21:49:18Z pgess
+?>
\ No newline at end of file
diff --git a/documentation/Syntax/syntax.xml b/documentation/Syntax/syntax.xml
index e03c42a..95f2184 100644
--- a/documentation/Syntax/syntax.xml
+++ b/documentation/Syntax/syntax.xml
@@ -1,707 +1,956 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Syntax</title>
+ <?xxe-sn 26yv439af40 59?>
+
+ <title><?xxe-sn 26yv439af40 5a?>Syntax</title>
+
+ <para><?xxe-sn 26yv439af40 5b?><informaltable>
+ <?xxe-sn 26yv439af40 5c?>
- <para><informaltable>
<tgroup cols="3">
+ <?xxe-sn 26yv439af40 5d?>
+
<tbody>
+ <?xxe-sn 26yv439af40 5e?>
+
<row>
- <entry>Literals, Expressions, Basic Statements</entry>
+ <?xxe-sn 26yv439af40 5f?>
+
+ <entry><?xxe-sn 26yv439af40 5g?>Literals, Expressions, Basic
+ Statements</entry>
- <entry>Annotations</entry>
+ <entry><?xxe-sn 26yv439af40 5h?>Annotations</entry>
- <entry>Intrinsics: query</entry>
+ <entry><?xxe-sn 26yv439af40 5i?>Intrinsics: query</entry>
</row>
<row>
- <entry>Identifiers, Code Blocks</entry>
+ <?xxe-sn 26yv439af40 5j?>
+
+ <entry><?xxe-sn 26yv439af40 5k?>Identifiers, Code Blocks</entry>
- <entry>Branch Statements</entry>
+ <entry><?xxe-sn 26yv439af40 5l?>Branch Statements</entry>
- <entry>Interfaces: Extern-C</entry>
+ <entry><?xxe-sn 26yv439af40 5m?>Interfaces: Extern-C</entry>
</row>
<row>
- <entry>Functions</entry>
+ <?xxe-sn 26yv439af40 5n?>
- <entry>Loops</entry>
+ <entry><?xxe-sn 26yv439af40 5o?>Functions</entry>
- <entry>Other: Transcend, Versions</entry>
+ <entry><?xxe-sn 26yv439af40 5p?>Loops</entry>
+
+ <entry><?xxe-sn 26yv439af40 5q?>Other: Transcend, Versions</entry>
</row>
<row>
- <entry>Types</entry>
+ <?xxe-sn 26yv439af40 5r?>
+
+ <entry><?xxe-sn 26yv439af40 5s?>Types</entry>
- <entry>Variants</entry>
+ <entry><?xxe-sn 26yv439af40 5t?>Variants</entry>
- <entry/>
+ <entry><?xxe-sn 26yv439af40 5u?></entry>
</row>
</tbody>
</tgroup>
</informaltable></para>
- <para>There are number of principles Xreate syntax based on:</para>
+ <para><?xxe-sn 26yv439af40 5v?>There are number of principles Xreate syntax
+ based on:</para>
<itemizedlist>
+ <?xxe-sn 26yv439af40 5w?>
+
<listitem>
- <para>Follows SSA form: each identifier is defined only once and no
- redefinitions allowed</para>
+ <?xxe-sn 26yv439af40 5x?>
+
+ <para><?xxe-sn 26yv439af40 5y?>Follows SSA form: each identifier is
+ defined only once and no redefinitions allowed</para>
</listitem>
<listitem>
- <para>Order in which identifiers are defined does not influence
- computation order. Identifiers are computed in order based on
- dependencies between expressions. Order in which identifiers are defines
- reflects preferences and what is convenient for a developer.</para>
+ <?xxe-sn 26yv439af40 5z?>
+
+ <para><?xxe-sn 26yv439af40 60?>Order in which identifiers are defined
+ does not influence computation order. Identifiers are computed in order
+ based on dependencies between expressions. Order in which identifiers
+ are defines reflects personal preferences and what is convenient for a
+ developer.</para>
</listitem>
</itemizedlist>
<section>
- <title>Literals and expressions</title>
+ <?xxe-sn 26yv439af40 61?>
+
+ <title><?xxe-sn 26yv439af40 62?>Literals and expressions</title>
- <para>In Xreate expressions have a form:</para>
+ <para><?xxe-sn 26yv439af40 63?>Xreate expressions have a form:</para>
- <synopsis>SYNTAX:
+ <synopsis><?xxe-sn 26yv439af40 64?>SYNTAX:
//expression// [:: //type//; //annotations-list// ]</synopsis>
- <para>where <emphasis>annotation-list</emphasis> is a list of annotations
- delimited by semicolon.</para>
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 fd?>
- <para>Expressions consist of literals and various operations as
- follows:</para>
+ <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">
- <colspec colwidth="115*"/>
+ <?xxe-sn 26yv439af40 69?>
+
+ <colspec colwidth="115*"><?xxe-sn 26yv439af40 6a?></colspec>
- <colspec colwidth="885*"/>
+ <colspec colwidth="885*"><?xxe-sn 26yv439af40 6b?></colspec>
<tbody>
+ <?xxe-sn 26yv439af40 6c?>
+
<row>
- <entry>Literals</entry>
+ <?xxe-sn 26yv439af40 6d?>
+
+ <entry><?xxe-sn 26yv439af40 6e?>Literals</entry>
- <entry>numbers, strings: <code>5, "Nimefurahi
- kukujua"</code></entry>
+ <entry><?xxe-sn 26yv439af40 6f?>numbers, strings: <code><?xxe-sn 26yv439af40 6g?>5,
+ "Nimefurahi kukujua"</code></entry>
</row>
<row>
- <entry>Lists, records</entry>
+ <?xxe-sn 26yv439af40 6h?>
+
+ <entry><?xxe-sn 26yv439af40 6i?>Lists, records</entry>
- <entry>Record is a collection of elements of different types -
- <code>{year = 1934, month = "april"}</code>. List is a collection
- of elements of the same type without keys - <code>{16, 8,
+ <entry><?xxe-sn 26yv439af40 6j?>Record is a collection of elements
+ of different types - <code><?xxe-sn 26yv439af40 6k?>{year = 1934,
+ month = "april"}</code>. List is a collection of elements of the
+ same type without keys - <code><?xxe-sn 26yv439af40 6l?>{16, 8,
3}</code></entry>
</row>
<row>
- <entry>Arithmetic operations</entry>
+ <?xxe-sn 26yv439af40 6m?>
- <entry>Basic arithmetic operations: <code>+, -, *,
- /</code></entry>
+ <entry><?xxe-sn 26yv439af40 6n?>Arithmetic operations</entry>
+
+ <entry><?xxe-sn 26yv439af40 6o?>Basic arithmetic operations:
+ <code><?xxe-sn 26yv439af40 6p?>+, -, *, /</code></entry>
</row>
<row>
- <entry>Relations</entry>
+ <?xxe-sn 26yv439af40 6q?>
+
+ <entry><?xxe-sn 26yv439af40 6r?>Relations</entry>
- <entry><code>==, !=, &lt;&gt;, &lt;, &lt;=, &gt;, &gt;=</code>.
- Both <code>!=, &lt;&gt;</code> mean <emphasis>not equal</emphasis>
- relation. Examples: <code>8&gt;=3, "Blue" &lt;&gt;
+ <entry><?xxe-sn 26yv439af40 6s?><code><?xxe-sn 26yv439af40 6t?>==,
+ !=, &lt;&gt;, &lt;, &lt;=, &gt;, &gt;=</code>. Both
+ <code><?xxe-sn 26yv439af40 6u?>!=, &lt;&gt;</code> mean
+ <emphasis><?xxe-sn 26yv439af40 6v?>not equal</emphasis> relation.
+ Examples: <code><?xxe-sn 26yv439af40 6w?>8&gt;=3, "Blue" &lt;&gt;
"Green"</code></entry>
</row>
<row>
- <entry>List and struct operations</entry>
+ <?xxe-sn 26yv439af40 6x?>
+
+ <entry><?xxe-sn 26yv439af40 6y?>List and struct operations</entry>
- <entry><emphasis>index</emphasis> operation to access individual
- elements of a list or a record. Example: <code>colors = {"Green",
+ <entry><?xxe-sn 26yv439af40 6z?><emphasis><?xxe-sn 26yv439af40 70?>index</emphasis>
+ operation to access individual elements of a list or a record.
+ Example: <code><?xxe-sn 26yv439af40 71?>colors = {"Green",
"Blue"}::[string]. color = colors[0]:: string.</code> Record's
- element access: <code>date = {year = 1934, month = "april"}. year
- = date["year"]</code></entry>
+ element access: <code><?xxe-sn 26yv439af40 72?>date = {year =
+ 1934, month = "april"}. year = date["year"]</code></entry>
</row>
<row>
- <entry>Identifiers</entry>
+ <?xxe-sn 26yv439af40 73?>
- <entry>Example: <code>a - b</code></entry>
+ <entry><?xxe-sn 26yv439af40 74?>Identifiers</entry>
+
+ <entry><?xxe-sn 26yv439af40 75?>Example: <code><?xxe-sn 26yv439af40 76?>a
+ - b</code></entry>
</row>
<row>
- <entry>Functions</entry>
+ <?xxe-sn 26yv439af40 77?>
+
+ <entry><?xxe-sn 26yv439af40 78?>Functions</entry>
- <entry>Example: <code>result = isOdd(6).</code></entry>
+ <entry><?xxe-sn 26yv439af40 79?>Example: <code><?xxe-sn 26yv439af40 7a?>result
+ = isOdd(6).</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
- <title>Code Blocks</title>
+ <?xxe-sn 26yv439af40 7b?>
+
+ <title><?xxe-sn 26yv439af40 7c?>Code Blocks</title>
- <para>Block is a list of expressions delimited by period. It has a
- <emphasis>body</emphasis> - main expression and optionally some identifier
- definitions.</para>
+ <para><?xxe-sn 26yv439af40 7d?>Block is a list of expressions delimited by
+ period. It has a <emphasis><?xxe-sn 26yv439af40 7e?>body</emphasis> - main
+ expression and optionally some identifier definitions.</para>
- <synopsis>SYNTAX:
+ <synopsis><?xxe-sn 26yv439af40 7f?>SYNTAX:
{
[//ident// = //expression// . | //body-expression// . ]..
}</synopsis>
- <para>Code block consists of expression called <emphasis>body
+ <para><?xxe-sn 26yv439af40 7g?>Code block consists of <emphasis><?xxe-sn 26yv439af40 7h?>body
expression</emphasis> and optional set of assignments to define
- identifiers used by body expression. Block computation is defined as
- result of associated body expression computation. If any expression
- encountered during computation includes some identifiers they are computed
- first.</para>
+ identifiers used in body expression. Block's computation is defined as a
+ result of associated body expression's computation. Identifiers are
+ computed before expressions they are used in.</para>
- <programlisting xml:id="CodeBlocks1">test = function:: int
+ <programlisting xml:id="CodeBlocks1"><?xxe-sn 26yv439af40 7i?>name="tests/ast.cpp: AST.Doc_CodeBlocks1"
+test = function:: int
{
a = 10:: int.
b = 2:: int.
a + b:: int
}</programlisting>
- <para>Above is an example of code block which have <code>a+b</code> as a
- body expression. In this case body depends on identifiers <code>a</code>,
- <code>b</code> so compiler computes both of them beforehand.</para>
+ <para><?xxe-sn 26yv439af40 7j?>Above is an example of code block which
+ have <code><?xxe-sn 26yv439af40 7k?>a+b</code> as a body expression. In
+ this case body depends on identifiers <code><?xxe-sn 26yv439af40 7l?>a</code>,
+ <code><?xxe-sn 26yv439af40 7m?>b</code> so compiler computes both of them
+ beforehand.</para>
- <para>Computation order depends only on dependencies between expressions.
- This approach has properties as follows:</para>
+ <para><?xxe-sn 26yv439af40 7n?>Computation order depends only on
+ dependencies between expressions. This approach has properties as
+ follows:</para>
<itemizedlist>
+ <?xxe-sn 26yv439af40 7o?>
+
<listitem>
- <para>Mutually independent identifiers can be evaluated in any
- order</para>
+ <?xxe-sn 26yv439af40 7p?>
+
+ <para><?xxe-sn 26yv439af40 7q?>Mutually independent identifiers can be
+ evaluated in any order</para>
</listitem>
<listitem>
- <para>Identifier gets computed only if it's required by block body
- expression or other required identifier</para>
+ <?xxe-sn 26yv439af40 7r?>
+
+ <para><?xxe-sn 26yv439af40 7s?>Identifier gets computed only if it's
+ required(even transitively) by block's body expression.</para>
</listitem>
</itemizedlist>
</section>
<section>
- <title>Functions</title>
+ <?xxe-sn 26yv439af40 7t?>
+
+ <title><?xxe-sn 26yv439af40 7u?>Functions</title>
- <synopsis>SYNTAX:
+ <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>
- <para><emphasis>function-name</emphasis> name of function</para>
+ <?xxe-sn 26yv439af40 7x?>
+
+ <para><?xxe-sn 26yv439af40 7y?><emphasis><?xxe-sn 26yv439af40 7z?>function-name</emphasis>
+ name of function</para>
</listitem>
<listitem>
- <para><emphasis>argument</emphasis> formal parameter. Arguments
- delimited by comma.</para>
+ <?xxe-sn 26yv439af40 80?>
+
+ <para><?xxe-sn 26yv439af40 81?><emphasis><?xxe-sn 26yv439af40 82?>argument</emphasis>
+ formal parameter. Arguments are delimited by comma.</para>
</listitem>
<listitem>
- <para><emphasis>type</emphasis>, <emphasis>return-type</emphasis>
- formal parameter and returning value types</para>
+ <?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 and returning value types</para>
</listitem>
<listitem>
- <para><emphasis>function-block</emphasis> code block that holds
- function definition</para>
+ <?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>
- <para><emphasis>annotations</emphasis> list of annotations delimited
- by semicolon</para>
+ <?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>Below is an example of a function <code>sum</code>. It takes two
- arguments and returns their sum. Also it has few annotations. First
- annotation <code>entry</code> has a special meaning - it depicts entry
- point or main function in a program. Second annotation
- <code>status(needs_review)</code> is an example that developers can
- annotate function using custom annotations to express different
- properties.</para>
-
- <programlisting xml:id="Functions1">sum = function(x:: int, y:: int):: int; entry; status(needs_review)
+ <para><?xxe-sn 26yv439af40 8d?>Below is an example of a function
+ <code><?xxe-sn 26yv439af40 8e?>sum</code>. It takes two arguments and
+ returns their sum. Also it defines several annotations. First annotation
+ <code><?xxe-sn 26yv439af40 8f?>entry</code> has a special meaning — it
+ depicts entry point or main function in a program. Second annotation
+ <code><?xxe-sn 26yv439af40 8g?>status(needs_review)</code> is a
+ demonstration that developers can annotate function using custom
+ annotations to express different 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>
- <title>Function Specializations</title>
+ <?xxe-sn 26yv439af40 8i?>
- <synopsis>SYNTAX:
+ <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>
- <para><emphasis>annotation</emphasis> Guard expressed by
- annotation</para>
+ <?xxe-sn 26yv439af40 8m?>
+
+ <para><?xxe-sn 26yv439af40 8n?><emphasis><?xxe-sn 26yv439af40 8o?>annotation</emphasis>
+ Guard expressed by annotation</para>
</listitem>
<listitem>
- <para><emphasis>functions-list</emphasis> one or more function that
- share the same guard</para>
+ <?xxe-sn 26yv439af40 8p?>
+
+ <para><?xxe-sn 26yv439af40 8q?><emphasis><?xxe-sn 26yv439af40 8r?>functions-list</emphasis>
+ one or more function that share the same guard</para>
</listitem>
</itemizedlist>
- <para>Xreate allows several functions called
- <emphasis>specializations</emphasis> to share the same name. This is
- syntactic foundation for <emphasis>function level polymorphism</emphasis>
+ <para><?xxe-sn 26yv439af40 8s?>Xreate allows several functions to share
+ the same name. In which case they are called <emphasis><?xxe-sn 26yv439af40 fk?>
+ specializations</emphasis>. This is syntactic foundation for
+ <emphasis><?xxe-sn 26yv439af40 8u?>function level polymorphism</emphasis>,
i.e. ability for compiler to decide which exactly function is called out
- of several options. Resolution can happen during compilation or at
- run-time.</para>
+ of several options. Polymorphism resolution can happen during compilation
+ or at run-time.</para>
- <para>Functions with the same name i.e. different specializations should
- have unique identifiers called <emphasis>guards</emphasis>. When function
- is actually called it's expected that resolution is already done at some
+ <para><?xxe-sn 26yv439af40 8v?>Functions with the same name, i.e.
+ different specializations should have additional unique identifiers called
+ <emphasis><?xxe-sn 26yv439af40 8w?>guards</emphasis>. When function is
+ actually called it's expected that resolution is already done at some
point before and supplies correct guard to uniquely specify which exactly
specialization to call.</para>
- <para>Example:</para>
+ <para><?xxe-sn 26yv439af40 8x?>Example:</para>
- <programlisting xml:id="FunctionSpecialization1">guard:: safe_enviroment
+ <programlisting xml:id="FunctionSpecialization1"><?xxe-sn 26yv439af40 8y?>name="tests/ast.cpp: AST.Doc_FunctionSpecializations1"
+guard:: safe_enviroment
{
sum = function (a::int, b::int) :: int
{
a + b
}
}</programlisting>
<note>
- <para>See <link
- xlink:href="/w/transcend/ast-api#function-s-specializatio">API</link> to
- get more information on how guards are processed</para>
+ <?xxe-sn 26yv439af40 8z?>
+
+ <para><?xxe-sn 26yv439af40 90?>See <link
+ xlink:href="/w/transcend/ast-api#function-s-specializatio"><?xxe-sn 26yv439af40 91?>API</link>
+ to get more information on how guards are processed</para>
</note>
</section>
<section>
- <title>Branch Statements</title>
+ <?xxe-sn 26yv439af40 92?>
+
+ <title><?xxe-sn 26yv439af40 93?>Branch Statements</title>
<section>
- <title>IF Statement</title>
+ <?xxe-sn 26yv439af40 94?>
- <synopsis>SYNTAX:
+ <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>IF statement executes <emphasis>block-true</emphasis> or
- <emphasis>block-false</emphasis> depending on
- <emphasis>condition</emphasis> evaluation result.</para>
+ <para><?xxe-sn 26yv439af40 97?><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 <emphasis><?xxe-sn 26yv439af40 9a?>condition</emphasis> evaluation
+ result.</para>
- <para>Example:</para>
+ <para><?xxe-sn 26yv439af40 9b?>Example:</para>
- <programlisting xml:id="IfStatement1">answer = if (question == "Favorite color?"):: string
+ <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>
- <title>SWITCH Statement</title>
+ <?xxe-sn 26yv439af40 9d?>
+
+ <title><?xxe-sn 26yv439af40 9e?>SWITCH Statement</title>
- <synopsis>SYNTAX:
+ <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>
- <para><emphasis>condition</emphasis>'s result is used to decide
- which branch to execute next</para>
+ <?xxe-sn 26yv439af40 9h?>
+
+ <para><?xxe-sn 26yv439af40 9i?><emphasis><?xxe-sn 26yv439af40 9j?>condition</emphasis>'s
+ result is used to decide which branch to execute next</para>
</listitem>
<listitem>
- <para><emphasis>guard</emphasis> value to match against
- <emphasis>condition</emphasis></para>
+ <?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>
- <para><emphasis>default-code-block</emphasis> executed if no
- appropriate case found</para>
+ <?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>SWITCH statement evaluation's result is that of branch whose
- <emphasis>guard</emphasis> matches
- <emphasis>condition</emphasis>.</para>
+ <para><?xxe-sn 26yv439af40 9r?>SWITCH statement evaluation's result is
+ that of branch whose <emphasis><?xxe-sn 26yv439af40 9s?>guard</emphasis>
+ matches <emphasis><?xxe-sn 26yv439af40 9t?>condition</emphasis>.</para>
- <para>Example:</para>
+ <para><?xxe-sn 26yv439af40 9u?>Example:</para>
- <programlisting xml:id="SwitchStatement1">monthName = switch(monthNum) :: string
+ <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 {"Strange.. Don't know this month"}.</programlisting>
</section>
</section>
<section>
- <title>Loop Statements</title>
+ <?xxe-sn 26yv439af40 9w?>
+
+ <title><?xxe-sn 26yv439af40 9x?>Loop Statements</title>
<section>
- <title>LOOP Statement</title>
+ <?xxe-sn 26yv439af40 9y?>
- <synopsis>SYNTAX:
+ <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>
- <para><emphasis>init-value</emphasis> initial value loop starts
- from</para>
+ <?xxe-sn 26yv439af40 a2?>
+
+ <para><?xxe-sn 26yv439af40 a3?><emphasis><?xxe-sn 26yv439af40 a4?>init-value</emphasis>
+ initial value loop starts from</para>
</listitem>
<listitem>
- <para><emphasis>accumulator</emphasis> identifier which holds loop's
- result after each iteration</para>
+ <?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>For each iteration <emphasis>accumulator</emphasis> assumes result
- of previous iteration or <emphasis>init-value</emphasis> during first
- iteration. Result of the <emphasis>loop-body</emphasis> evaluation is
- used as <emphasis>accumulator</emphasis>'s next iteration value and as
- overall loop statement result after the last iteration.</para>
+ <para><?xxe-sn 26yv439af40 a8?>For each iteration <emphasis><?xxe-sn 26yv439af40 a9?>accumulator</emphasis>
+ assumes result of previous iteration or <emphasis><?xxe-sn 26yv439af40 aa?>init-value</emphasis>
+ during first iteration. Result of the <emphasis><?xxe-sn 26yv439af40 ab?>loop-body</emphasis>
+ evaluation is used as <emphasis><?xxe-sn 26yv439af40 ac?>accumulator</emphasis>'s
+ next iteration value and as overall loop statement result after the last
+ iteration.</para>
- <para>This notation does not have termination condition. Compiler relies
- on loop body fixed point in order to decide when to interrupt loop.
- Let's consider example:</para>
+ <para><?xxe-sn 26yv439af40 ad?>This notation does not have termination
+ condition. Compiler relies on loop body's fixed point in order to decide
+ when to interrupt loop. Let's consider example:</para>
- <programlisting xml:id="LoopStatement1">COUNTEREXAMPLE
+ <programlisting xml:id="LoopStatement1"><?xxe-sn 26yv439af40 ae?>COUNTEREXAMPLE, name="tests/ast.cpp: AST.Doc_LoopStatements"
//infinite loop
answer = loop (2-&gt;x) :: int
{
if(IsPerfect(x)):: int {x} else {x+1}
}.</programlisting>
- <para>The example tests numbers for being perfect(sum of all proper
- divisors equals to the number itself). While iterating accumulator
- <code>x</code> assumes values as follows: 2, 3, 4, 5, 6, 6 ... After it
- founds first perfect number any further iteration do not change result
- anymore since there is no increment and it continues to test the same
- number again and again. Obviously, <code>x=6</code> is a fixed point in
+ <para><?xxe-sn 26yv439af40 af?>The example tests numbers for being
+ perfect(sum of all proper divisors equals to the number itself). While
+ iterating accumulator <code><?xxe-sn 26yv439af40 ag?>x</code> assumes
+ values as follows: 2, 3, 4, 5, 6, 6 ... After it founds first perfect
+ number any further iteration do not change result anymore since there is
+ no increment and it continues to test the same number again and again.
+ Obviously, <code><?xxe-sn 26yv439af40 ah?>x=6</code> is a fixed point in
this example. There is no point to continue going through further
iterations once fixed point is evaluated and hence loop can be safely
interrupted.</para>
- <para>Compiler relies on manually provided annotations to recognize when
- fixed point is reached. There is special annotation <code>final</code>
- to specify fixed point for loops. Once expression marked as
- <code>final</code> gets evaluated it's assumed to be fixed point or in
- other words compiler knows it's the very last iteration after which loop
- ends. Correct code for the example above is:</para>
+ <para><?xxe-sn 26yv439af40 ai?>Compiler relies on manually provided
+ annotations to recognize when fixed point is reached. There is special
+ annotation <code><?xxe-sn 26yv439af40 aj?>final</code> to specify fixed
+ point for loops. Once expression marked as <code><?xxe-sn 26yv439af40 ak?>final</code>
+ gets evaluated it's assumed to be a fixed point or in other words
+ compiler knows it's the very last iteration after which loop ends.
+ Correct code for the example above is:</para>
- <programlisting xml:id="LoopStatement2">//loop exits after first perfect number is found
+ <programlisting xml:id="LoopStatement2"><?xxe-sn 26yv439af40 al?>name="tests/ast.cpp: AST.Doc_LoopStatements"
+//loop exits after first perfect number is found
answer2 = loop (2-&gt;x) :: int
{
if(IsPerfect(x))::int {x:: int; final} else {x+1}
}.</programlisting>
- <para>In this case compiler able to recognize when fixed point is
- reached to exit loop. After loops is done <code>answer</code> is
- <code>6</code>.</para>
+ <para><?xxe-sn 26yv439af40 am?>In this case compiler able to recognize
+ when fixed point is reached to exit loop. After loops is done
+ <code><?xxe-sn 26yv439af40 an?>answer</code> is <code><?xxe-sn 26yv439af40 ao?>6</code>.</para>
</section>
<section>
- <title>LOOP FOLD Statement</title>
+ <?xxe-sn 26yv439af40 ap?>
- <synopsis>SYNTAX:
+ <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>
- <para><emphasis>list</emphasis> to iterate through</para>
+ <?xxe-sn 26yv439af40 at?>
+
+ <para><?xxe-sn 26yv439af40 au?><emphasis><?xxe-sn 26yv439af40 av?>list</emphasis>
+ to iterate through</para>
</listitem>
<listitem>
- <para><emphasis>element</emphasis> identifier that assumes value of
- currently processed list element</para>
+ <?xxe-sn 26yv439af40 aw?>
+
+ <para><?xxe-sn 26yv439af40 ax?><emphasis><?xxe-sn 26yv439af40 ay?>element</emphasis>
+ identifier that assumes value of currently processed list
+ element</para>
</listitem>
<listitem>
- <para><emphasis>type</emphasis>, <emphasis>annotations</emphasis>
- expression types and optional annotations delimited by
- semicolon</para>
+ <?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>
- <para><emphasis>init-value</emphasis> accumulator's initial value
- loop starts with</para>
+ <?xxe-sn 26yv439af40 b3?>
+
+ <para><?xxe-sn 26yv439af40 b4?><emphasis><?xxe-sn 26yv439af40 b5?>init-value</emphasis>
+ accumulator's initial value loop starts with</para>
</listitem>
<listitem>
- <para><emphasis>accumulator</emphasis> identifier assumes loop-body
- evaluation result after each iteration</para>
+ <?xxe-sn 26yv439af40 b6?>
+
+ <para><?xxe-sn 26yv439af40 b7?><emphasis><?xxe-sn 26yv439af40 b8?>accumulator</emphasis>
+ identifier assumes loop-body evaluation result after each
+ iteration</para>
</listitem>
</itemizedlist>
- <para>Iterates over <emphasis>list</emphasis> in order to accumulate
- result by applying <emphasis>loop-body</emphasis> transformation to each
- <emphasis>element</emphasis> and intermediate
- <emphasis>accumulator</emphasis>. Overall loop value is a accumulator's
- value after the last iteration. If fixed point is found an execution
- terminates earlier.</para>
+ <para><?xxe-sn 26yv439af40 b9?>Iterates over <emphasis><?xxe-sn 26yv439af40 ba?>list</emphasis>
+ in order to accumulate result by applying <emphasis><?xxe-sn 26yv439af40 bb?>loop-body</emphasis>
+ transformation to each <emphasis><?xxe-sn 26yv439af40 bc?>element</emphasis>
+ and intermediate <emphasis><?xxe-sn 26yv439af40 bd?>accumulator</emphasis>.
+ Overall loop value is a accumulator's value after the last iteration. If
+ fixed point is found an execution terminates earlier.</para>
- <para>Example shows code excerpt that looks for a minimal element in the
- given list(and less then initial value <code>10</code>).</para>
+ <para><?xxe-sn 26yv439af40 be?>Example shows code excerpt that looks for
+ a minimal element in the given list(and less then initial value
+ <code><?xxe-sn 26yv439af40 bf?>10</code>).</para>
- <programlisting xml:id="FoldStatement1">numbers = {4, 8, 7, 1, 5}:: [int].
+ <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>
- <title>LOOP MAP Statement</title>
+ <?xxe-sn 26yv439af40 bh?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 26yv439af40 bi?>LOOP MAP Statement</title>
-**loop map** ( //list// **-&gt;** //element// :: //type// [; //annotations// ] ) :: //type// [; //annotations// ]
+ <synopsis><?xxe-sn 26yv439af40 bj?>SYNTAX:
+**loop map** (//list// **-&gt;** //element// :: //type// [; //annotations// ] ) :: //type// [; //annotations// ]
//loop-body//</synopsis>
<itemizedlist>
+ <?xxe-sn 26yv439af40 bk?>
+
<listitem>
- <para><emphasis>list</emphasis> to iterate through</para>
+ <?xxe-sn 26yv439af40 bl?>
+
+ <para><?xxe-sn 26yv439af40 bm?><emphasis><?xxe-sn 26yv439af40 bn?>list</emphasis>
+ to iterate through</para>
</listitem>
<listitem>
- <para><emphasis>element</emphasis> identifier that assumes value of
- currently processed list element</para>
+ <?xxe-sn 26yv439af40 bo?>
+
+ <para><?xxe-sn 26yv439af40 bp?><emphasis><?xxe-sn 26yv439af40 bq?>element</emphasis>
+ identifier that assumes value of currently processed list
+ element</para>
</listitem>
<listitem>
- <para><emphasis>type</emphasis>, <emphasis>annotations</emphasis>
- type and optional annotations delimited by semicolon.</para>
+ <?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>
<listitem>
- <para><emphasis>loop-body</emphasis></para>
+ <?xxe-sn 26yv439af40 bv?>
+
+ <para><?xxe-sn 26yv439af40 bw?><emphasis><?xxe-sn 26yv439af40 bx?>loop-body</emphasis></para>
</listitem>
</itemizedlist>
- <para>Iterates over input <emphasis>list</emphasis> and applies
- <emphasis>loop-body</emphasis> transformation to each element. Result is
- a list that consists of all transformed elements.</para>
+ <para><?xxe-sn 26yv439af40 by?>Iterates over input <emphasis><?xxe-sn 26yv439af40 bz?>list</emphasis>
+ and applies <emphasis><?xxe-sn 26yv439af40 c0?>loop-body</emphasis>
+ transformation to each element. Result is a list that consists of all
+ transformed elements.</para>
- <programlisting xml:id="MapStatement1">odd_numbers = {1, 3, 5}:: [int].
+ <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>
- <para>Example demonstrates creating <code>even_number</code> list by
- multiplying by 2 every element of <code>odd_numbers</code>.</para>
+ <para><?xxe-sn 26yv439af40 c2?>Example demonstrates creating
+ <code><?xxe-sn 26yv439af40 c3?>even_number</code> list by multiplying by
+ 2 every element of <code><?xxe-sn 26yv439af40 c4?>odd_numbers</code>.</para>
</section>
</section>
<section>
- <title>Types</title>
+ <?xxe-sn 26yv439af40 c5?>
- <para>Primitive Types</para>
+ <title><?xxe-sn 26yv439af40 c6?>Types</title>
+
+ <para><?xxe-sn 26yv439af40 c7?>Primitive Types</para>
<informaltable>
+ <?xxe-sn 26yv439af40 c8?>
+
<tgroup cols="2">
- <colspec colwidth="173*"/>
+ <?xxe-sn 26yv439af40 c9?>
+
+ <colspec colwidth="173*"><?xxe-sn 26yv439af40 ca?></colspec>
- <colspec colwidth="827*"/>
+ <colspec colwidth="827*"><?xxe-sn 26yv439af40 cb?></colspec>
<tbody>
+ <?xxe-sn 26yv439af40 cc?>
+
<row>
- <entry><code>num</code></entry>
+ <?xxe-sn 26yv439af40 cd?>
+
+ <entry><?xxe-sn 26yv439af40 ce?><code><?xxe-sn 26yv439af40 cf?>num</code></entry>
- <entry><code>i32</code> alias. Reserved for auto detected most
- appropriate either integral of floating-point number type</entry>
+ <entry><?xxe-sn 26yv439af40 cg?><code><?xxe-sn 26yv439af40 ch?>i32</code>
+ alias. Reserved for auto detected most appropriate either integral
+ of floating-point number type</entry>
</row>
<row>
- <entry><code>int</code></entry>
+ <?xxe-sn 26yv439af40 ci?>
+
+ <entry><?xxe-sn 26yv439af40 cj?><code><?xxe-sn 26yv439af40 ck?>int</code></entry>
- <entry><code>i32</code> alias. Reserved for auto detected most
- appropriate integral number type</entry>
+ <entry><?xxe-sn 26yv439af40 cl?><code><?xxe-sn 26yv439af40 cm?>i32</code>
+ alias. Reserved for auto detected most appropriate integral number
+ type</entry>
</row>
<row>
- <entry><code>float</code></entry>
+ <?xxe-sn 26yv439af40 cn?>
- <entry>Double precision floating-point number</entry>
+ <entry><?xxe-sn 26yv439af40 co?><code><?xxe-sn 26yv439af40 cp?>float</code></entry>
+
+ <entry><?xxe-sn 26yv439af40 cq?>Double precision floating-point
+ number</entry>
</row>
<row>
- <entry><code>bool</code></entry>
+ <?xxe-sn 26yv439af40 cr?>
+
+ <entry><?xxe-sn 26yv439af40 cs?><code><?xxe-sn 26yv439af40 ct?>bool</code></entry>
- <entry>Boolean type</entry>
+ <entry><?xxe-sn 26yv439af40 cu?>Boolean type</entry>
</row>
<row>
- <entry><code>i8, i32, i64</code></entry>
+ <?xxe-sn 26yv439af40 cv?>
+
+ <entry><?xxe-sn 26yv439af40 cw?><code><?xxe-sn 26yv439af40 cx?>i8,
+ i32, i64</code></entry>
- <entry>Signed integers. 8, 32, 64 bit wide respectively</entry>
+ <entry><?xxe-sn 26yv439af40 cy?>Signed integers. 8, 32, 64 bit
+ wide respectively</entry>
</row>
<row>
- <entry><code>string</code></entry>
+ <?xxe-sn 26yv439af40 cz?>
- <entry>Pointer to a null terminated ANSI char string. Reserved for
- auto detected most appropriate string type.</entry>
+ <entry><?xxe-sn 26yv439af40 d0?><code><?xxe-sn 26yv439af40 d1?>string</code></entry>
+
+ <entry><?xxe-sn 26yv439af40 d2?>Pointer to a null terminated ANSI
+ char string. Reserved for auto detected most appropriate string
+ type.</entry>
</row>
<row>
- <entry><code>*</code></entry>
+ <?xxe-sn 26yv439af40 d3?>
+
+ <entry><?xxe-sn 26yv439af40 d4?><code><?xxe-sn 26yv439af40 d5?>*</code></entry>
- <entry>Unspecified type. Example <code>x = {amount=200,
+ <entry><?xxe-sn 26yv439af40 d6?>Unspecified type. Example
+ <code><?xxe-sn 26yv439af40 d7?>x = {amount=200,
currency="USD"}::*.</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
- <para>Compound types:</para>
+ <para><?xxe-sn 26yv439af40 d8?>Compound types:</para>
<informaltable>
+ <?xxe-sn 26yv439af40 d9?>
+
<tgroup cols="2">
- <colspec colwidth="312*"/>
+ <?xxe-sn 26yv439af40 da?>
- <colspec colwidth="688*"/>
+ <colspec colwidth="312*"><?xxe-sn 26yv439af40 db?></colspec>
+
+ <colspec colwidth="688*"><?xxe-sn 26yv439af40 dc?></colspec>
<tbody>
+ <?xxe-sn 26yv439af40 dd?>
+
<row>
- <entry><code>[ <emphasis>element-type</emphasis> ]</code></entry>
+ <?xxe-sn 26yv439af40 de?>
+
+ <entry><?xxe-sn 26yv439af40 df?><code><?xxe-sn 26yv439af40 dg?>[
+ <emphasis><?xxe-sn 26yv439af40 dh?>element-type</emphasis>
+ ]</code></entry>
- <entry>List of elements of the same type
- <emphasis>element-type</emphasis>. Example: <code>[int]</code> -
- list of <code>int</code>'s</entry>
+ <entry><?xxe-sn 26yv439af40 di?>List of elements of the same type
+ <emphasis><?xxe-sn 26yv439af40 dj?>element-type</emphasis>.
+ Example: <code><?xxe-sn 26yv439af40 dk?>[int]</code> - list of
+ <code><?xxe-sn 26yv439af40 dl?>int</code>'s</entry>
</row>
<row>
- <entry><code>{<emphasis>key</emphasis>::
- <emphasis>type</emphasis>, ...}</code></entry>
+ <?xxe-sn 26yv439af40 dm?>
- <entry>List of elements of different type possibly with named
- keys. Examples: <code>{int, string}</code>, <code>{name::string,
+ <entry><?xxe-sn 26yv439af40 dn?><code><?xxe-sn 26yv439af40 do?>{<emphasis><?xxe-sn 26yv439af40 dp?>key</emphasis>::
+ <emphasis><?xxe-sn 26yv439af40 dq?>type</emphasis>,
+ ...}</code></entry>
+
+ <entry><?xxe-sn 26yv439af40 dr?>List of elements of different type
+ possibly with named keys. Examples: <code><?xxe-sn 26yv439af40 ds?>{int,
+ string}</code>, <code><?xxe-sn 26yv439af40 dt?>{name::string,
age::int}</code></entry>
</row>
<row>
- <entry><code>variant {<emphasis>option</emphasis> ::
- (<emphasis>type</emphasis>, ...}, ...}</code></entry>
+ <?xxe-sn 26yv439af40 du?>
+
+ <entry><?xxe-sn 26yv439af40 dv?><code><?xxe-sn 26yv439af40 dw?>variant
+ {<emphasis><?xxe-sn 26yv439af40 dx?>option</emphasis> ::
+ (<emphasis><?xxe-sn 26yv439af40 dy?>type</emphasis>, ...},
+ ...}</code></entry>
- <entry>Holds a single element of type of one out of number of
- options. Examples: <code>variant {FullAddress:: {string, string,
- string}, ShortAddress:: {string}}</code></entry>
+ <entry><?xxe-sn 26yv439af40 dz?>Holds a single element of type of
+ one out of number of options. Examples: <code><?xxe-sn 26yv439af40 e0?>variant
+ {FullAddress:: {string, string, string}, ShortAddress::
+ {string}}</code></entry>
</row>
<row>
- <entry><code>slave <emphasis>identifier</emphasis></code></entry>
+ <?xxe-sn 26yv439af40 e1?>
+
+ <entry><?xxe-sn 26yv439af40 e2?><code><?xxe-sn 26yv439af40 e3?>slave
+ <emphasis><?xxe-sn 26yv439af40 e4?>identifier</emphasis></code></entry>
- <entry>Type determined by Transcend. Example: <code>slave
+ <entry><?xxe-sn 26yv439af40 e5?>Type determined by Transcend.
+ Example: <code><?xxe-sn 26yv439af40 e6?>slave
unit_test</code></entry>
</row>
<row>
- <entry><code><emphasis>compound-type</emphasis> [
- <emphasis>key</emphasis> ]</code></entry>
+ <?xxe-sn 26yv439af40 e7?>
- <entry>Accessing elements of compound type. Example: <code>Bio =
- type {birth_year:: int, name:: string}. Year = type
+ <entry><?xxe-sn 26yv439af40 e8?><code><?xxe-sn 26yv439af40 e9?><emphasis><?xxe-sn 26yv439af40 ea?>compound-type</emphasis>
+ [ <emphasis><?xxe-sn 26yv439af40 eb?>key</emphasis>
+ ]</code></entry>
+
+ <entry><?xxe-sn 26yv439af40 ec?>Accessing elements of compound
+ type. Example: <code><?xxe-sn 26yv439af40 ed?>Bio = type
+ {birth_year:: int, name:: string}. Year = type
Bio[birth_year].</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
- <para>New types defined as:</para>
-
- <synopsis>SYNTAX:
+ <para><?xxe-sn 26yv439af40 ee?>New types defined as:</para>
+ <synopsis><?xxe-sn 26yv439af40 ef?>SYNTAX:
//type-name// = **type** (//parameters//...) //type-definition// .</synopsis>
- <para>Example:</para>
+ <para><?xxe-sn 26yv439af40 eg?>Example:</para>
- <programlisting xml:id="Types1">Tuple = type {string, int}.
+ <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</programlisting>
</section>
<section>
- <title>Variants and SWITCH VARIANT Instruction</title>
+ <?xxe-sn 26yv439af40 ei?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 26yv439af40 ej?>Variants and SWITCH VARIANT
+ Instruction</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>
- <para><emphasis>condition</emphasis> expression of variant type</para>
+ <?xxe-sn 26yv439af40 em?>
+
+ <para><?xxe-sn 26yv439af40 en?><emphasis><?xxe-sn 26yv439af40 eo?>condition</emphasis>
+ expression of variant type</para>
</listitem>
<listitem>
- <para><emphasis>alias</emphasis> identifier to denote unwrapped
- content of condition withing case branches.</para>
+ <?xxe-sn 26yv439af40 ep?>
+
+ <para><?xxe-sn 26yv439af40 eq?><emphasis><?xxe-sn 26yv439af40 er?>alias</emphasis>
+ identifier to denote unwrapped content of condition withing case
+ branches.</para>
</listitem>
<listitem>
- <para><emphasis>guard</emphasis> name of variant to match against
- actual condition's variant</para>
+ <?xxe-sn 26yv439af40 es?>
+
+ <para><?xxe-sn 26yv439af40 et?><emphasis><?xxe-sn 26yv439af40 eu?>guard</emphasis>
+ name of variant to match against actual condition's variant</para>
</listitem>
<listitem>
- <para><emphasis>case-branch</emphasis> block of code to execute in
- case of matched variant. Content is accessible by using alias Within
- the branch .</para>
+ <?xxe-sn 26yv439af40 ev?>
+
+ <para><?xxe-sn 26yv439af40 ew?><emphasis><?xxe-sn 26yv439af40 ex?>case-branch</emphasis>
+ block of code to execute in case of matched variant. Content is
+ accessible by using alias Within the branch .</para>
</listitem>
</itemizedlist>
- <para>Sometimes it is useful for a variable to have value of different
- types depending on some conditions, in other words it has
- <emphasis>variant type</emphasis>.</para>
+ <para><?xxe-sn 26yv439af40 ey?>Sometimes it is useful for a variable to
+ have value of different types depending on some conditions, in other words
+ it has <emphasis><?xxe-sn 26yv439af40 ez?>variant type</emphasis>.</para>
- <para>Let's consider example with variable <emphasis>month</emphasis> of
- variant type <emphasis>Month</emphasis>:</para>
+ <para><?xxe-sn 26yv439af40 f0?>Let's consider example with variable
+ <code><?xxe-sn 26yv439af40 fi?>month</code> of variant type
+ <code><?xxe-sn 26yv439af40 fj?>Month</code>:</para>
- <programlisting xml:id="Variants1">Month = type variant {
+ <programlisting xml:id="Variants1"><?xxe-sn 26yv439af40 f3?>name="tests/ast.cpp: AST.Doc_Variants"
+Month = type variant {
MonName :: {string},
MonNumber:: {int}
}.
test = function:: Month
{
month = MonName("April"):: Month.
month
}</programlisting>
- <para>Variable <code>month</code> holds value of either
- <code>string</code> or <code>int</code> type. Value is not accessible
- directly. It should be <emphasis>unwrapped</emphasis> before using. Xreate
- supports <code>switch variant</code> instruction for this
- operation.</para>
+ <para><?xxe-sn 26yv439af40 f4?>Variable <code><?xxe-sn 26yv439af40 f5?>month</code>
+ holds value of either <code><?xxe-sn 26yv439af40 f6?>string</code> or
+ <code><?xxe-sn 26yv439af40 f7?>int</code> type. Value is not accessible
+ directly. It should be <emphasis><?xxe-sn 26yv439af40 f8?>unwrapped</emphasis>
+ before using. Xreate supports <code><?xxe-sn 26yv439af40 f9?>switch variant</code>
+ instruction for this operation.</para>
- <para>As an example below is <code>nextMonth</code> function
- definition:</para>
+ <para><?xxe-sn 26yv439af40 fa?>As an example below is function
+ <code><?xxe-sn 26yv439af40 fb?>nextMonth</code>'s definition:</para>
- <programlisting>nextMonth = funcrtion(month:: Month):: Month
+ <programlisting><?xxe-sn 26yv439af40 fc?>nextMonth = function(month:: Month):: Month
{
switch variant(month):: Month
case (MonName)
{
//
}
case (MonNumber)
-
}</programlisting>
</section>
</chapter>
+<?xxe-revisions
+#2 2018-12-18T15:50:51Z pgess
+#1 2018-12-18T15:11:23Z pgess
+1sPEAAABgeJVADCB4lkAABkQc+xgE5kzQ5JQgwhTshozg19DkFhTCmODEwDsX5kyEZJXshmDXoYP
+ilQ=
+
+?>
\ No newline at end of file
diff --git a/documentation/Transcend/ast-api.xml b/documentation/Transcend/ast-api.xml
index 75f4cb0..5fae63b 100644
--- a/documentation/Transcend/ast-api.xml
+++ b/documentation/Transcend/ast-api.xml
@@ -1,450 +1,495 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<title>AST API</title>
<para>In order to reason about program, code model is translated into form
suited for processing by Transcend. Translation details are described
below.</para>
<section>
<title>Expression Annotations: 'bind'</title>
<synopsis>SYNTAX:
**bind**(//symbol-ref//, //annotation//)</synopsis>
<itemizedlist>
<listitem>
- <para><emphasis>symbol-ref</emphasis> assigned reference to the
- expression or identifier</para>
+ <para><emphasis>symbol-ref</emphasis> reference to the expression or
+ identifier</para>
</listitem>
<listitem>
<para><emphasis>annotation</emphasis> expression's annotation</para>
</listitem>
</itemizedlist>
- <para>Generated for each expression's annotation. Example:</para>
+ <para>Declares expression's annotations.</para>
- <programlisting>x = 5:: int; expected(even_number).</programlisting>
+ <para>Example:</para>
+
+ <programlisting xml:id="ExprAnn_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int
+{
+ x = 5:: int; expected(even_number).
+
+ x
+}</programlisting>
<para>gets translated into:</para>
- <programlisting>bind(v(1,-2,0), expected(even_number)).</programlisting>
+ <programlisting xml:id="Output_ExprAnn_1">bind(s(1,-2,0),expected(even_number)) </programlisting>
</section>
<section>
<title>Code Block: 'scope'</title>
<synopsis>SYNTAX:
**scope**(//scope-ref//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> reference to the code
block</para>
</listitem>
</itemizedlist>
<para>Declares code block under its unique reference identifier.</para>
<para>Example:</para>
- <programlisting>{
- x = 0.3:: float.
- y = 0.8:: float.
+ <programlisting xml:id="CodeBlock_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: float
+{
+ x = 3:: float.
+ y = 8:: float.
x + y
}</programlisting>
- <para>Translation result: <code>scope(2).</code></para>
+ <para>Translation result: <code
+ xml:id="Output_CodeBlock_1">scope(0)</code></para>
</section>
<section>
<title>Code Block Annotations: 'bind_scope'</title>
+ <warning>
+ <para>Pending syntax changes</para>
+ </warning>
+
<synopsis>SYNTAX:
**bind_scope**(//scope-ref//, //annotation//, strong) (1)
**bind_scope**(//scope-ref//, //annotation//, weak(..)) (2)
</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> child block's reference</para>
</listitem>
<listitem>
<para><emphasis>annotation</emphasis> code block's annotation</para>
</listitem>
</itemizedlist>
<para>Declares code block's annotations called
<emphasis>context</emphasis>. There are two forms for different context'
type:</para>
<itemizedlist>
<listitem>
<para><emphasis>strong</emphasis> context known at compile time</para>
</listitem>
<listitem>
<para><emphasis>weak</emphasis> possible context, can't be decided for
sure at compile time</para>
</listitem>
</itemizedlist>
<para>Example:</para>
- <programlisting>{
- context:: arithmetic(fast).
+ <programlisting xml:id="CodeBlockAnns_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: float
+{
+ context:: arithmetic(fast).
- x = 0.3:: float.
- y = 0.8:: float.
+ x = 3:: float.
+ y = 8:: float.
x + y
}</programlisting>
<para>Translation's result:</para>
- <programlisting>bind_scope(0, arithmetic(fast), strong).</programlisting>
+ <programlisting xml:id="Output_CodeBlockAnns_1">bind_scope(0,arithmetic(fast),strong)</programlisting>
</section>
<section>
<title>Code Block Bindings: 'ast_scope_binding'</title>
<synopsis>SYNTAX:
-**ast_scope_binding**(//scope-ref//, //binding-id//, //binding-alias//)
-</synopsis>
+**ast_scope_binding**(//scope-ref//, //binding-id//, //binding-alias//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> code block's reference</para>
</listitem>
<listitem>
<para><emphasis>binding-id</emphasis> number of code block's
binding</para>
</listitem>
<listitem>
<para><emphasis>binding-alias</emphasis> name of a binding</para>
</listitem>
</itemizedlist>
- <para>Code blocks can have <emphasis>bindings</emphasis>, i.e. Identifiers
- that have special meaning within a block. Declared for each block's
- binding.</para>
+ <para>Code blocks have zero or more <emphasis>bindings</emphasis>, i.e.
+ Identifiers that have special meaning within the block. Predicate declares
+ such code block's bindings. Bindings organized into ordered list. Order is
+ conveyed by specifying <emphasis>binding-id</emphasis> for each
+ <emphasis>binding-alias.</emphasis></para>
<para>Example:</para>
- <programlisting>loop ( 0 -&gt; acc ) :: int
+ <programlisting xml:id="CodeBlockBinds_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int
{
- if(acc &gt; 10) {acc:: int; final} else {acc + 1}
+ loop ( 0 -&gt; acc ):: int
+ {
+ if(acc &gt; 10):: int {acc:: int; final} else {acc + 1}
+ }
}</programlisting>
- <para>Translation result: <code>ast_scope_binding(2, 0, acc)</code></para>
+ <para>Translation result: <code
+ xml:id="Output_CodeBlockBinds_1">ast_scope_binding(1,0,"acc")</code></para>
</section>
<section>
<title>Code Block Parents: 'cfa_parent'</title>
<synopsis>SYNTAX:
-**cfa_parent**(//scope-ref//, scope(//scope-parent-ref//))</synopsis>
+**cfa_parent**(//scope-ref//, **scope**(//scope-parent-ref//))</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> child block's reference</para>
</listitem>
<listitem>
<para><emphasis>scope-parent-ref</emphasis> parent block's
reference</para>
</listitem>
</itemizedlist>
<para>Represents nested code blocks structure in terms of
<emphasis>child-parent</emphasis> relation.</para>
<para>Example:</para>
- <programlisting>{
+ <programlisting xml:id="CodeBlockParents_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int
+{
+ x = 19:: int.
+
if (x&gt;5):: int {x + 1} else {x - 1}
}</programlisting>
<para>Translation's result:</para>
- <programlisting>cfa_parent(1, scope(0)).
+ <programlisting xml:id="Output_CodeBlockParents_1">cfa_parent(1, scope(0)).
cfa_parent(2, scope(0)).</programlisting>
</section>
<section>
<title>Function: 'function'</title>
<synopsis>SYNTAX:
**function**(//fn-name//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> function name</para>
</listitem>
</itemizedlist>
- <para>Declares function known by its name.</para>
+ <para>Declares function identified by its name.</para>
<para>Example:</para>
- <programlisting>test = function:: int {0}</programlisting>
+ <programlisting xml:id="Fn_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int {0}</programlisting>
- <para>Translation's result: <code>function(test)</code></para>
+ <para>Translation's result: <code
+ xml:id="Output_Fn_1">function(test)</code></para>
</section>
<section>
<title>Function's Annotations: 'bind_func'</title>
<synopsis>SYNTAX:
**bind_func**(//fn-name//, //annotation//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> function's name</para>
</listitem>
</itemizedlist>
<para>Declares function's annotations.</para>
<para>Example:</para>
- <programlisting>test = function:: int; status(obsolete) {0}</programlisting>
+ <programlisting xml:id="FnAnns_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int; status(obsolete) {0}</programlisting>
- <para>Translation's result:
- <code>bind_func(test,status(obsolete))</code></para>
+ <para>Translation's result: <code
+ xml:id="Output_FnAnns_1">bind_func(test,status(obsolete))</code></para>
</section>
<section>
<title>Function's Specialization: 'cfa_function_specializations'</title>
<synopsis>SYNTAX:
**cfa_function_specializations**(//fn-name//, //guard//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> name of function</para>
</listitem>
<listitem>
<para><emphasis>guard</emphasis> specialization guard</para>
</listitem>
</itemizedlist>
<para>There is a possibility to have several functions with the same name
called specializations. Each specialization is uniquely determined by
annotation of special kind called <emphasis>guard</emphasis>.</para>
<para>Example:</para>
- <programlisting>guard:: arch(amd64)
+ <programlisting xml:id="FnSpecs_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+guard:: arch(amd64)
{
test = function:: i64 {0}
}</programlisting>
- <para>Translation's result:
- <code>cfa_function_specializations(test,arch(amd64))</code><note>
+ <para>Translation's result: <code
+ xml:id="Output_FnSpecs_1">cfa_function_specializations(test,arch(amd64))</code><note>
<para>See also <link
xlink:href="/w/syntax#function-specializations">specializations
syntax</link></para>
</note></para>
</section>
<section>
<title>Function's Entry: 'cfa_parent'</title>
<synopsis>SYNTAX:
**cfa_parent**(//scope-entry-ref//, functon(//fn-name//))</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-entry-ref</emphasis> function's entry code block
reference</para>
</listitem>
<listitem>
<para><emphasis>fn-name</emphasis> function's name</para>
</listitem>
</itemizedlist>
<para>Each function has a single <emphasis>entry</emphasis> code block and
is declared in terms of <emphasis>child-parent</emphasis> relation between
entry block(which is top-level in blocks hierarchy of the given function)
and the function itself.</para>
<para>Example:</para>
- <programlisting>test = function:: int {0}</programlisting>
+ <programlisting xml:id="FnEntry_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int {0}</programlisting>
- <para>Translation's result: <code>cfa_parent(0,
- function(test))</code></para>
+ <para>Translation's result: <code
+ xml:id="Output_FnEntry_1">cfa_parent(0,function(test))</code></para>
</section>
<section>
<title>Function's Result: 'dfa_fnret'</title>
<synopsis>SYNTAX:
**dfa_fnret**(//fn-name//, //symbol-ret-ref//)</synopsis>
<itemizedlist>
<listitem>
<para>symbol-ret-ref reference to a function's return
expression</para>
</listitem>
</itemizedlist>
<para>Specifies which expression is used to compute function's return
value.</para>
<para>Example:</para>
- <programlisting>test = function:: int {0}</programlisting>
+ <programlisting xml:id="FnResult_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int {0}</programlisting>
- <para>Translation's result: <code>dfa_fnret(test, v(0,-2,0))</code></para>
+ <para>Translation's result: <code
+ xml:id="Output_FnResult_1">dfa_fnret(test,s(0,-2,0))</code></para>
</section>
<section>
<title>Operations. Invocation: 'cfa_call', 'dfa_callfn',
'dfa_callargs'</title>
<synopsis>SYNTAX:
**cfa_call**(//scope-caller-ref//, //fn-callee-name//) (1)
**dfa_callfn**(//symbol-ref//, //fn-callee-name//) (2)
**dfa_callargs**(//symbol-ref//, //arg-formal-name//, //arg-actual-ref//) (3)
**weak**(**dfa_callargs**(//symbol-ref//, //arg-formal-name//, //arg-actual-ref//)) (4)
</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-caller-ref</emphasis> caller's code block's
reference</para>
</listitem>
<listitem>
<para><emphasis>fn-callee-name</emphasis> callee function name</para>
</listitem>
<listitem>
<para><emphasis>symbol-ref</emphasis> invocation operation
reference</para>
</listitem>
<listitem>
<para><emphasis>arg-formal-name</emphasis> function's formal
argument</para>
</listitem>
<listitem>
<para><emphasis>arg-actual-ref</emphasis> actual argument
reference</para>
</listitem>
</itemizedlist>
<para>Each function invocation is transformed into several transcend facts
as explained below:</para>
<informaltable>
<tgroup cols="2">
<colspec colwidth="225*"/>
<colspec colwidth="775*"/>
<tbody>
<row>
<entry>(1) <code>cfa_call</code></entry>
<entry>Specifies caller's code block and callee function
name</entry>
</row>
<row>
<entry>(2) <code>dfa_callfn</code></entry>
<entry>Declares unique reference to a particular invocation
site.The reference used by other facts to supply additional
information</entry>
</row>
<row>
<entry>(3) <code>dfa_callargs</code></entry>
<entry>Declares assignment relations between actual arguments and
formal arguments</entry>
</row>
<row>
<entry>(4) <code>weak(dfa_callargs)</code></entry>
<entry>The same as form (3). <emphasis>Weak</emphasis> relation
used in cases when there is no enough information at compile time.
One such case is when several function specializations exist and
it's impossible to say which exactly specialization is
called</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>Example:</para>
- <programlisting>inc = function (x::int) :: int {x + 1}
+ <programlisting xml:id="OpInvoc_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+inc = function (x::int):: int
+{
+ x + 1
+}
-main = function:: int
+main = function:: int
{
- arg = 10:: int
+ arg = 10:: int.
inc(arg)
}</programlisting>
<para>After translation following transcend facts are present:</para>
- <programlisting>cfa_call(1, test)
-dfa_callfn(v(0,1,-2), test)
-dfa_callargs(v(0,1,-2), x, v(1,1,-2)</programlisting>
+ <programlisting xml:id="Output_OpInvoc_1">cfa_call(1,inc)
+dfa_callfn(s(0,-2,1),inc)
+weak(dfa_callargs(s(0,-2,1),s(1,-2,0),s(1,-2,1)))
+dfa_callargs(s(0,-2,1),s(1,-2,0),s(1,-2,1))</programlisting>
</section>
<section>
<title>Operations. Loops</title>
<synopsis>**ast_op_map**(//symbol-result-ref//, //symbol-source-ref//, //loop-body-ref//)
**ast_op_fold**(//symbol-result-ref//, //symbol-source-ref//, //symbol-acc-ref//, //loop-body-ref//)</synopsis>
<itemizedlist>
<listitem>
<para>symbol-source-ref input list reference</para>
</listitem>
<listitem>
<para>symbol-acc-ref accumulator reference</para>
</listitem>
<listitem>
<para>symbol-result-ref result list reference</para>
</listitem>
<listitem>
- <para>loop-body-ref refers to a loop body's code block</para>
+ <para>loop-body-ref refers to a loop body expression</para>
</listitem>
</itemizedlist>
<para>Facts declare loop operations.</para>
<para>Example:</para>
- <programlisting>singles = {1, 2, 3}:: [int].
-doubles = loop map(singles-&gt;element)::[int]{2 * element}</programlisting>
+ <programlisting xml:id="OpLoops_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
+test = function:: int; entry
+{
+ singles = {1, 2, 3}:: [int].
+ doubles = loop map(singles-&gt;element:: int)::[int] {2 * element}.
+ doubles[0]
+}</programlisting>
- <para>produces fact: <code>ast_op_map(v(0,-2,0),v(1,-2,0),1)</code></para>
+ <para>produces fact: <code
+ xml:id="Output_OpLoops_1">ast_op_map(s(2,-2,0),s(1,-2,0),s(0,-2,1))</code></para>
</section>
</chapter>
diff --git a/documentation/Transcend/latetranscend.xml b/documentation/Transcend/latetranscend.xml
index e627b48..fb97ae8 100644
--- a/documentation/Transcend/latetranscend.xml
+++ b/documentation/Transcend/latetranscend.xml
@@ -1,168 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<title>Late Transcend</title>
<para>Transcend is a powerful tool and as a consequence it's computationally
inefficient. Well, expressiveness has its cost. That's the reason why it's
mostly suited only for a compile time where it shines unequivocally.
Obviously, at this stage compiler lacks dynamic part - the data that is
known for sure only during actual program execution. In other words, Early
Transcend reasons over <emphasis>weak</emphasis> data - set of facts
reflecting possible states and conditions the program could go through
during execution. Before that, there is no way to be sure what exactly is
going to happen, only set of possibilities is available. Nevertheless, in
many cases it's not enough and that's why <emphasis>Late
Transcend</emphasis> is introduced - reasoning and making decisions based on
data available at runtime.</para>
<para>Late Transcend approach can be described as having three
phases:</para>
<itemizedlist>
<listitem>
<para>Input: at compile time Transcend working with weak data produces
decisions for all possible alternatives. Generated set is used as an
input for Late Transcend. As it's unknown which exactly decision turns
out to be true, every decision has a <emphasis>guards</emphasis> - set
of pairs <emphasis>(variable, value)</emphasis> that describe exact
state for which it's possible to reach given decision.</para>
</listitem>
<listitem>
<para>Validation: A decision is considered to be valid only if all
guards are met, i.e. variables from guard pairs actually have required
values. In a sense Late Transcend decisions are deferred until
correspondent preconditions proved to be true.</para>
</listitem>
<listitem>
<para>Execution: DIfferent <emphasis>guarded</emphasis> decisions may
produce different code branches. All correspondent code branches are
compiled and present in the code in order to be used when needed. At
branching point guards are tested and appropriate branch is selected to
be executed next.</para>
</listitem>
</itemizedlist>
<section>
<title>Late Annotations and ASP Representation</title>
<para><emphasis>Late annotations</emphasis> is a particular type of
annotations that depend on parameters known only at runtime.
Example:</para>
- <programlisting>y = mul(a, b)::float; arithmetic(ArithmX)</programlisting>
+ <programlisting xml:id="LateAnn_1">name="tests/latetranscend.cpp: LateReasoning.Doc_SwitchLateOperation"
+mul(a, b)::float; arithmetic(ArithmX)</programlisting>
<para>Suppose we have different specializations of <code>mul</code>
function each implementing different multiplication precision and it
controlled by using <code>arithmetic(fast)</code>,
<code>arithmetic(accurate)</code> and similar annotations. In this example
<code>arithmetic(ArithmX)</code> is a late annotation, if
<code>ArithmX</code> is a parameter known only during program
execution.</para>
<para>Currently, late annotations do not differ syntactically from other
annotations. Only if annotation is recognized to have late arguments it's
marked internally as a <emphasis>late</emphasis> and special rules of
conversion to ASP form apply.</para>
- <para>Late annotation in ASP form presented as follows:</para>
+ <para>Late annotation in ASP form is presented as follows:</para>
- <synopsis>**late**(//target//, (//guard-identifiers-list//), (//guard-values-list//), //body//):- //parameter-types-list//. </synopsis>
+ <synopsis>SYNTAX:
+**late**(//target//, (//guard-identifiers-list//), (//guard-values-list//), //body//):- //parameter-types-list//. </synopsis>
<itemizedlist>
<listitem>
<para><emphasis>target</emphasis> References entity for which late
annotation is applicable</para>
</listitem>
<listitem>
<para><emphasis>guard-identifiers-list</emphasis> List of guard
identifiers</para>
</listitem>
<listitem>
<para>guard-values-list List of guard values</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para><emphasis>body</emphasis> Decision deemed valid if guards are
met</para>
</listitem>
<listitem>
<para><emphasis>parameter-types-list</emphasis> List of types of late
parameters</para>
</listitem>
</itemizedlist>
<para>Meaning that a fact <code>body</code> wrapped by modifier
<code>late()</code> alongside with two lists: guards' identifiers and
guards' values.</para>
<para>For an example above, <code>arithmetic(ArithmX)</code> translated
into form below where exact references depend on a program:</para>
- <programlisting>late(s(0,-2,2), (s(1,-2,2)), (ArithmX), arithmetic(ArithmX)):- arithmetic(ArithmX).</programlisting>
+ <programlisting xml:id="Output_LateAnn_1">late(s(0,-2,2), (s(1,-2,2)), (ArithmX), arithmetic(ArithmX)):- arithmetic(ArithmX).</programlisting>
<para>This rule generates different facts for each possible <code>x</code>
alternative. At runtime only those facts are selected whose guards are
met, i.e. referenced variables actually have specified values.</para>
</section>
<section>
<title>Switch Late Operation</title>
<synopsis>SYNTAX:
**switch late** ( //condition// [-&gt; //alias// ] [:: //condition-type// [; //annotations-list//] ] ) :: //type// [; //annotations-list//]
//switch-block//</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>condition</emphasis> switch's condition</para>
</listitem>
<listitem>
<para><emphasis>alias</emphasis> optional alias to denote condition's
result within internal code block annotations. If there is no alias
and condition is just one identifier it's accessible by its own
name</para>
</listitem>
<listitem>
<para>condition-type Condition must have slave type</para>
</listitem>
</itemizedlist>
<para>Switch Late operation allows to designate <emphasis>alias</emphasis>
as a <emphasis>late parameter</emphasis> to use in late annotation. It can
be conceptualised as lifting Brute value to Transcend level. During
compilation it generates different <emphasis>switch-block</emphasis>
branches for each possible condition value and only branch is executed
whose guard correspond condition. Example:</para>
- <programlisting>ArithmeticT = type slave arithmetic.
+ <programlisting xml:id="SwitchLate_1">name="tests/latetranscend.cpp: LateReasoning.Doc_SwitchLateOperation"
+ArithmeticT = type slave arithmetic.
-test = function(a::float, b::float, ArithmX::ArithmeticT):: float; entry
+test = function(a::float, b::float, ArithmX::ArithmeticT):: float; entry
{
switch late (ArithmX):: float
{
mul(a, b)::float; arithmetic(ArithmX)
}
}</programlisting>
<para>Compiler generates several branches for all possible
<code>arithmetic</code> variants. Only one branch executed depending on
<code>arithmX</code>.</para>
</section>
</chapter>
diff --git a/documentation/exploitation.xml b/documentation/exploitation.xml
new file mode 100644
index 0000000..43ac71c
--- /dev/null
+++ b/documentation/exploitation.xml
@@ -0,0 +1,487 @@
+<?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 1?>
+
+ <title><?xxe-sn 26yv439af40 2?>Exploitation</title>
+
+ <para><?xxe-sn 26yv439af40 6?>This chapter discusses <emphasis><?xxe-sn 26yv439af40 7?>exploiting</emphasis>
+ external resources, such as files, as a particular instance of a
+ <emphasis><?xxe-sn 26yv439af40 8?>side effects</emphasis> problem that
+ inevitably stems from an interaction with the outside world. Unlike <link
+ xlink:href="/w/virtualization"><?xxe-sn 295bzzou9kw 2?>virtualization</link>,
+ an another documentation's topic that tackles I/O, exploitation approaches
+ subject from a different angle — it is concerned with an <emphasis><?xxe-sn 26yv439af40 x?>order
+ of operations</emphasis>, sequence in which different clients jointly use
+ the same resource and it deals with corresponding difficulties, e.g. ensures
+ proper resource initialization before actual usage.</para>
+
+ <section>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8v?>
+
+ <title><?xxe-sn 29je46abuev -wunr7fl0rw8u?>Syntax</title>
+
+ <section>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8s?>
+
+ <title><?xxe-sn 29je46abuev -wunr7fl0rw8r?>Annotations</title>
+
+ <synopsis><?xxe-sn 29je46abuev -wunr7fl0rw8q?>SYNTAX:
+**use**(//resource-id//)
+**init**(//resource-id//)</synopsis>
+
+ <itemizedlist>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8p?>
+
+ <listitem>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8o?>
+
+ <para><?xxe-sn 29je46abuev -wunr7fl0rw8n?><emphasis><?xxe-sn 29je46abuev -wunr7fl0rw8m?>resource-id</emphasis>
+ — user-defined resource identifier</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 29je46abuev -wunr7fl0rw8l?>Annotates function or code
+ block as such that exploits resource <emphasis><?xxe-sn 29je46abuev -wunr7fl0rw8k?>resource-id</emphasis>.
+ </para>
+ </section>
+
+ <section>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8j?>
+
+ <title><?xxe-sn 29je46abuev -wunr7fl0rw8i?>Guards</title>
+
+ <synopsis><?xxe-sn 29je46abuev -wunr7fl0rw8h?>SYNTAX:
+**exploitation(init)**
+**exploitation(none)**</synopsis>
+
+ <para><?xxe-sn 29je46abuev -wunr7fl0rw8g?>Specializations that are
+ recognized by exploitation reasoning. Each specialization corresponds to
+ an initialization strategy:</para>
+
+ <itemizedlist>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8f?>
+
+ <listitem>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8e?>
+
+ <para><?xxe-sn 29je46abuev -wunr7fl0rw8d?><code><?xxe-sn 29je46abuev -wunr7fl0rw8a?>exploitation(init)</code>
+ is expected to perform actual resource initialization.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 29je46abuev -wunr7fl0rw8c?>
+
+ <para><?xxe-sn 29je46abuev -wunr7fl0rw8b?><code><?xxe-sn 29je46abuev -wunr7fl0rw89?>exploitation(none)</code>
+ is expected to do nothing as initialization isn't necessary or done
+ elsewhere. </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 3?>
+
+ <title><?xxe-sn 26yv439af40 4?>Background</title>
+
+ <para><?xxe-sn 26yv439af40 b?>In software engineering, the idea to avoid
+ side effects have received considerable traction. Indeed, side effects is
+ something that is hard to take into account and thus programs that have
+ side effects are inherently unsafe, thus best coding practices are
+ rightfully suggest to isolate side effects producing code as much as
+ possible. It's so called pure functional languages whose philosophy goes
+ even further and frames side effects as something opposite of "pure", and
+ everything is built around effectless computations to the point that some
+ languages' design itself includes side effects producing constructs, such
+ as I/O, as an afterthought, as something almost unnecessary.</para>
+
+ <para><?xxe-sn 26yv439af40 c?>However, in reality the opposite is true,
+ most applications' sole responsibility is to communicate with "outside
+ world", reacting to the external events and change "world state"
+ accordingly. As a consequence, side effects usually are the
+ <emphasis><?xxe-sn 26yv439af40 d?>only</emphasis> important effects the
+ program produce and surely deserve first class support from a programming
+ language and justify efforts to develop approach to alleviate related
+ safety and performance concerns.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 z?>
+
+ <title><?xxe-sn 26yv439af40 10?>Exploitation Plan</title>
+
+ <para><?xxe-sn 26yv439af40 12?>One complexity of taking side effects into
+ account is the fact that final result depends on an <emphasis><?xxe-sn 28ivhnywem8 1?>exact
+ operations order</emphasis>. This harshly impacts both performance and
+ safety, for many techniques, e.g. caching, parallelization can neither be
+ automatically performed nor validated since they are based on various
+ degrees of reordering or deal with possibly undetermined beforehand order
+ of execution.</para>
+
+ <para><?xxe-sn 28ivhnywem8 2?>In this chapter, it is assumed, that final
+ effects of execution fully defined by <emphasis><?xxe-sn 28ivhnywem8 3?>exploitation
+ path</emphasis> — for a particular code path that can occur during
+ execution, it is its part consisting of only relevant code blocks., i.e.
+ those that deal with an exploited resource. Other code blocks do not
+ influence exploitation effects and so are excluded from consideration.
+ Thus reasoning about effects is reduced to considering all possible
+ exploitation paths, checking do they meet certain requirements that define
+ valid exploitation and making corrections if needed and possible.</para>
+
+ <para><?xxe-sn 26yv439af40 13?>Result of the reasoning is called
+ <emphasis><?xxe-sn 26yv439af40 14?>exploitation plan</emphasis> —
+ specification that defines exact order and strategy of using a given
+ resource in order to comply with imposed requirements.</para>
+
+ <para><?xxe-sn 26yv439af40 15?>With all above said, the discussed approach
+ can be presented as follows:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 16?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 17?>
+
+ <para><?xxe-sn 26yv439af40 18?>Annotations are used to express some
+ aspects of side effects to enable further reasoning. They indicate
+ code blocks that deal with resource as well as provide additional
+ information about how exactly it is exploited, e.g. use, initialize or
+ deinitialize resource.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 28ivhnywem8 4?>
+
+ <para><?xxe-sn 28ivhnywem8 5?>Existing code paths, extracted during
+ source code processing, coupled with relevant annotations is enough to
+ construct all possible exploitation paths and analyze them. Analysis
+ determines possible(<emphasis><?xxe-sn 295bzzou9kw 3?>weak</emphasis>)
+ paths that can occur or not during particular execution as well as
+ certain paths(<emphasis><?xxe-sn 295bzzou9kw 4?>strong</emphasis>)
+ that occur always no matter what. Also it checks are exploitation
+ paths valid against certain rules, e.g. initialization occurs always
+ before actual usage and is it possible to correct invalid
+ paths.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 28ivhnywem8 6?>
+
+ <para><?xxe-sn 28ivhnywem8 7?>Reasoning's result is an exploitation
+ plan that dictates order and strategy of exploitation is presented in
+ form of appropriate specialization for polymorphic functions that deal
+ with resources in order to ensure safe exploitation to the extent
+ based on provided annotations.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 19?>
+
+ <para><?xxe-sn 26yv439af40 1a?>Exploitation related side effects are
+ viewed as a set of additional restrictions over operations order. Only
+ subset of possible reorders is still valid w.r.t. side effects.
+ Transcend's task is to find out refined set of valid orders. Thus
+ techniques that rely on reordering enjoy additional information to
+ make safe optimizations.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 1b?>... and it serves three major goals:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 1c?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 1d?>
+
+ <para><?xxe-sn 26yv439af40 1e?>Safety. Validates existing exploitation
+ plan or is it possible to safely exploit given resource at all.
+ Compiler signals error if a given exploitation plan is invalid, i.e.
+ does not satisfy requirements w.r.t. side effects as expressed by
+ annotations.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 28j5661y0mv -wunr7fl0rw8v?>
+
+ <para><?xxe-sn 28j5661y0mv -wunr7fl0rw8u?>Regression Resilience. When
+ it comes to using external resources, some spurious dependencies
+ usually occur between otherwise isolated, independent components of a
+ program. Sometimes refactoring and other code changes break those
+ dependencies inevitably introducing regressions. Exploitation catches
+ this sort of regressions and automatically regenerates exploitation
+ plan suited for a changed conditions.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 1f?>
+
+ <para><?xxe-sn 26yv439af40 1g?>Performance. Generated exploitation
+ plans are optimal in a sense that they cut off superfluous operations,
+ for example, removing resource initialization in several places if it
+ can be done safely in a single one, thus reducing overall
+ overhead.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <?xxe-sn 27ay8x1a5mo 1?>
+
+ <title><?xxe-sn 27ay8x1a5mo 2?>Domination Analysis</title>
+
+ <para><?xxe-sn 27ay8x1a5mo 3?>When it comes to a reasoning about order of
+ execution flow and possible code paths, crucial vehicle for that is
+ <emphasis><?xxe-sn 27ay8x1a5mo 4?>domination analysis</emphasis> producing
+ <emphasis><?xxe-sn 27ay8x1a5mo 5?>dominator tree</emphasis> as an
+ output.</para>
+
+ <para><?xxe-sn 27ay8x1a5mo 6?>Unlike the usual function-bounded domination
+ analysis, when separate domination tree is produced for each function
+ defined in a program, Exploitation requires program bound analysis, that
+ is to take into account control flow across all functions in a program. It
+ is computationally intensive task to perform analysis over a whole
+ program, however it is compensated by the fact that Exploitation only
+ takes into account code blocks that deal with, or in other words, exploit
+ external resources. Thus there is no necessity to build full dominator
+ tree, only the relevant parts are constructed, just enough to make sound
+ exploitation plan decisions.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 28h47d43thc i?>
+
+ <title><?xxe-sn 28h47d43thc j?>Empty Exploitation Plan. Effect Free
+ Computations</title>
+
+ <para><?xxe-sn 28h47d43thc k?>Validation of exploitation path is done
+ against some predefined constraints. Depending on complexity of a
+ constraints, i.e. number of different exploitation events that are seeking
+ for in each path, reasoning goals categorized into several groups:</para>
+
+ <itemizedlist>
+ <?xxe-sn 28j5661y0mv -wunr7fl0rw8t?>
+
+ <listitem>
+ <?xxe-sn 28j5661y0mv -wunr7fl0rw8s?>
+
+ <para><?xxe-sn 28j5661y0mv -wunr7fl0rw8r?>Zero Order Exploitation.
+ Meaning that all paths are checked in terms is there exploitation at
+ all or no, is there at least a single exploitation event along the
+ path.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 28j5661y0mv -wunr7fl0rw8q?>
+
+ <para><?xxe-sn 28j5661y0mv -wunr7fl0rw8p?>First Order Exploitation.
+ Deals with a situations when it's enough to check only two different
+ exploitation event occur in a required order. It can be useful for
+ example, to check whether all resource uses occur after it is
+ initialized.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 28j5661y0mv -wunr7fl0rw8o?>
+
+ <para><?xxe-sn 28j5661y0mv -wunr7fl0rw8n?>Higher Order Exploitation.
+ Expresses constraints involving several(more than two) exploitation
+ events and relations between them.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 28j5661y0mv -wunr7fl0rw8m?><emphasis><?xxe-sn 28j5661y0mv -wunr7fl0rw8l?>Empty
+ Exploitation</emphasis> is an important instance of zero order constraint.
+ It useful mechanism for developer to annotate function or part of a
+ program as effect free in terms of exploitation. Thus, efectless, clean or
+ pure code can be clearly separated from effectfull part and compiler
+ raises compilation error in case of accidental mixing or using "wrong"
+ type of code in non appropriate environment.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 u?>
+
+ <title><?xxe-sn 26yv439af40 v?>Resource Initialization</title>
+
+ <para><?xxe-sn 26yv439af40 w?>One important problem related to an
+ exploitation order is to ensure that a given resource is properly
+ initialized before its first usage and additionally it is not initialized
+ more then once during exploitation session. This is instance of first
+ order exploitation since in a validation mode it is enough to check
+ exploitation plan to ensure that every resource usage preceded by resource
+ initialization at some point in the <emphasis><?xxe-sn 28jw0wb6fpc 1?>past</emphasis>,
+ i.e. previously in the exploitation path.</para>
+
+ <para><?xxe-sn 28jw0wb6fpc 2?>For planning mode, the problem is addressed
+ as follows:</para>
+
+ <itemizedlist>
+ <?xxe-sn 28jw0wb6fpc 3?>
+
+ <listitem>
+ <?xxe-sn 28jw0wb6fpc 4?>
+
+ <para><?xxe-sn 28jw0wb6fpc 5?>Central idea of the algorithm is to
+ consider candidates for initialization only among code blocks that
+ <emphasis><?xxe-sn 295bzzou9kw 5?>dominate</emphasis> given usage
+ site. Obviously, initialization in dominating block precedes usage for
+ any possible code path.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 295bzzou9kw 6?>
+
+ <para><?xxe-sn 295bzzou9kw 7?>One or more dominator blocks are chosen
+ for actual initialization in such way that they are cover all found
+ usage sites.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 295bzzou9kw 8?>
+
+ <para><?xxe-sn 295bzzou9kw 9?>For code blocks chosen for
+ initialization specialization <code><?xxe-sn 295bzzou9kw a?>exploitation(init)</code>
+ is set, for the rest specialization <code><?xxe-sn 295bzzou9kw b?>exploitation(none)</code>
+ is used.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 28h47d43thc 1?>Look at the example below:</para>
+
+ <programlisting xml:id="ResourceInit_1"><?xxe-sn 28h47d43thc 2?>name="tests/exploitation.cpp: Doc_ResourceInit_1", lines=15
+import raw("scripts/cfa/payload.lp").
+import raw("scripts/exploitation/exploitation.lp"). //exploitation reasoning
+import raw("scripts/exploitation/test1.assembly.lp").
+
+guard:: exploitation(init)
+{
+ openFile = function(filePrev:: FILE_P):: FILE_P; init(file)
+ {
+ fopen("/tmp/test", "w")::FILE_P
+ }
+}
+
+guard:: exploitation(none)
+{
+ openFile = function(filePrev:: FILE_P):: FILE_P
+ {
+ filePrev::int
+ }
+}
+
+test = function:: int; entry
+{
+ seq
+ { f0 = undef:: FILE_P. f0 }
+ {
+ //Scope #1:
+ f1 = openFile(f0):: FILE_P.
+ f1
+ }
+
+ { //Scope #2:
+ f2 = openFile(f1):: FILE_P.
+ f2
+ }
+ {
+ //Scope #3:
+ sizeWritten = fwrite("Attempt to write..", 12, 1, f2):: int; use(file).
+ sizeWritten
+ }
+ {
+ //Scope #4:
+ fclose(f2):: int; use(file)
+ }
+ { sizeWritten :: int}
+}</programlisting>
+
+ <para><?xxe-sn 28h47d43thc 3?>There is the function <code><?xxe-sn 28h47d43thc 4?>test</code>
+ that executes sequentially next commands: open a file(scopes #1, #2),
+ write some text(scope #3) and finally, close the file(scope #4). It
+ represents simple work flow with an external resource.</para>
+
+ <para><?xxe-sn 28h47d43thc 7?>In order to connect the code to the
+ exploitation the functions <code><?xxe-sn 28h47d43thc 5?>fwrite</code> and
+ <code><?xxe-sn 28h47d43thc 6?>fclose</code> in scopes #3 and #4
+ respectively are annotated with annotation <code><?xxe-sn 295bzzou9kw c?>use(file)</code>.
+ This information is used by reasoning to look whether it is possible to
+ initialize given resource before actual usage as well as where and when
+ exactly to initialize it. Function <code><?xxe-sn 28h47d43thc 9?>openFile</code>
+ is annotated as <code><?xxe-sn 28h47d43thc a?>init(file)</code> meaning it
+ <emphasis><?xxe-sn 28h47d43thc b?>can</emphasis> initialize depending on
+ chosen strategy. The function is invoked both in scope #1 and scope #2.
+ Both scopes are executed <emphasis><?xxe-sn 28h47d43thc d?>strictly
+ before</emphasis> scopes #3, #4. Thus it is indeed possible to initialize
+ resource before usage. Next task for exploitation is to choose correct
+ exploitation plan, i.e. to assign strategies for all possible
+ initialization places in the effort to initialize resource only once.
+ Here, it means that only one invocation of <code><?xxe-sn 28h47d43thc e?>openFile</code>
+ is assigned with <code><?xxe-sn 28h47d43thc f?>exploitation(init)</code>
+ to actually initialize the file. Other one is automatically marked with
+ <code><?xxe-sn 28h47d43thc g?>exploitation(none)</code> to invoke
+ different specialization of <code><?xxe-sn 28h47d43thc h?>openFile</code>
+ that does nothing since the files is already initialized.</para>
+ </section>
+</chapter>
+<?xxe-revisions
+#11 2019-02-02T13:07:26Z pgess
+#10 2019-02-01T17:38:23Z pgess
+1sPEAAABgYUKAIFE9icACGZQc28yPz5sZWFziRsTC0MIQ2oTC2OCNgECQ4MkU4s0IwcTC2PCVFMF
+MyRTFgEDM4kVEwVDCmMJU4I8EwxThHozgVuDDEOBGoMIMwljVVMMQwVTPBMEAQMTBxMGYw5TbUMP
+Yx9TLHMQEwcTChMJUxYAiR6YbxmDNI5ygjqDMb5tjjuLSbZOimemdYERpyObYagAiSKDYoJMhH3i
+gWejny2BIIFcqCZl6Q6TG4l51AGZa4N5lkeBJZzSBZdFigWdWA==
+
+#9 2019-01-26T14:30:18Z pgess
+1sPEAAAB9icAUfYlAAEqIGRz0wATB0OBHVMEQxszCBMFQzRTBTMEYwdjgRgTCAEBY4I9MwpDgVxj
+m00Ap2mrJoRxiR2ZGo5OijKLeq8mnUlJhCOBG54rgkGBYw==
+#8 2019-01-15T20:23:54Z pgess
+1sPEAAAB9ioAhCvvEAAlgiWBWTphc3NvY+KAlENzVW5ld2Jyb2tld2lmb3JzIDh0cmlnZ2MzZWRz
+hjUTDkNNEwgjBVMPAQFDQVNUAQVjBCMHMwQTBjMIY4wxUwdDgw5jfwEDUwQzihsBAVMiIwVjgRFD
+BFNTYwYzgnoTByMGAQFDix3UEwxDCjMGMwxjBVM2YxozBc0TBkMWEyBjbFMJUyVjDhMIMzdji11T
+CEMHMxVTBwEFYwSkY4I8kxZTK2OLHFMYM1EBAjOBEhMRUw0TEEOBPUMdMwSTCDMFUwlDBwEEYxET
+CUMMUyAzim8zEUMcYwVTIRMSQxozgV1TEZMLAQFjE2MKEwcBBTMEgwxjC1MGYwQzBjMOQ4EbM4FY
+UwkTBGMXAQFTD0MIUw5jTSMEEwtTBwEBUwczGpMIQwgzBVMGAQJjgQYTBTMFkwhjBmMHcwVTCYME
+UwQzCUODSwCGSj+FZK15XBNPiyyLPJR1hWWUNYNkpX6MOIMfiRmBCIolnGArgTQQdhKbF60ngxKE
+KINihiyoLp1okBUHN4hQjnyjB404oSOUH4lodqw8hHBFO4ZOqxeLbIIllBGGCCpGrHyDDC6HLFip
+eZ4Bg3iBQYFqhwi+jEQfpVuYPIl8mXqLN4dsin4bj20rhGeZD0++OQWCBYFdllSWf+JYhH8Oymig
+CB+BHoFDok6fa5MkgieFGRKBGqJyzHaLRL41cCiqf69yhAWEe4FAcM5PhGACnnsZgT6gNho=
+#7 2019-01-15T13:53:13Z pgess
+1sPEAAAB7xAAIuoxAAAQDHPREhMKQwRTQBMJExBjmDgAog2uVjCJF4N4hUU=
+#6 2019-01-15T11:27:29Z pgess
+1sPEAAAB6jIAF+dpAAAKB3PMJBMJQylTmxMAiReKLbtb
+#5 2019-01-15T08:04:19Z pgess
+1sPEAAAB520AglrYYQAogTF6RGF0aXNvZmluIGxpbVN0bDo6IEMxakRlLCwsaGxsIEluIHNoYWJ1
+dHOjSwEDEwYBAiMEAQJDCmMEYwtDTGMFUyIzBzMGEw9TgyxDDxMFYwYTCSMFIwoTBTMKEwkzJgEG
+MwQzC1OCV+ETBQEBQ1pjCVMMM0djBgEBY4EBAQFDJVMxEwZjdxMMQy4BA1MJYxJjFjMgYwQTGwEC
+YxkBAUMGAQFjBFMGAQODCZMMgywBATMIMwQBBkMEExL5EwdDC0MHYxJDBQECUwSDCVOGCQEDQ4Na
+gwkzKVObEwCRFaoCiCekAopDFIULT3MjmUcbgweMEYRHhjqtBLRjhWyRCoRwkXWCKoEaPYFqh32C
+W4EahyZxhydMgQJfnjBHgzSFHYs5rTyVBJE+oEODeJFFjn6SK50Al37CmTiVDYJ8kR9Wi06ZMoMu
+EoEUnUCXizOGEJeKLY5K
+#4 2019-01-14T13:48:02Z pgess
+1sPEAAAB2GUAgSjKVwAOVz0zPz5UdHRlc2hvdWxTcnOVKhMWQ4IsEwzdUwUBAWMEUwdjCGMJIwYB
+ATMFAQFjBFMIEx9TNVMEMwRjC1MMUxEBBRMEMwkzgl5TCmMLgyBDIwEBY4FMMw0zBFMXM4pXEwUB
+AWOgfQCVTSKDNKlVixtjgU2UA4k+mUicDoljFoQumTyORYVtRoN7HZdigjEdkjOBQiyJVjmVRIRC
+gQeCUZlRh2Q=
+#3 2018-12-24T11:55:39Z pgess
+1sPEAAAByiAAglmxQABBgSBxZmxmbWZucmVzdWxpbmRpdmlkZG8gc28sIGJvZ3VzIGdsb2JpcyBs
+bCBsQ0ZHNz8+QS04Pz5mb3J3bzk/PnAvPgpzpUkTCwECQx8BAlMZUyUBAmMpM4EjU4IUYwgBBRMF
+Mw4TBhMJQwcBB2MMMwQTC0MgMwYzByMPQyVDCwERYwRDBRMFYwUzBEMJUwQTBAEDEwQzB+LWUw4B
+A0MKExBzCwEEUwUzBiMMAQEzCFMKYwQTF3MLAQczBFMHAQFDDTMGExRzCwEEQwSDByMPUwRDBRMF
+Qw1TKWOCS3MLAQETCAECAIM0DKp5LlmhW4E7gxWgXIJenROObIhji1uHGoNjOIxDiwt0S5NdhiSN
+F4xGlnaRBothlSWICkSYHIYbimyXV4I3g3jJhQKEEIIQi1uDJJ8LhCvJjEOBfINCl0GELsmHL8VC
+hTySPYYHhl2NPYcQxAE=
+#2 2018-12-24T11:20:18Z pgess
+1sPEAAABsUAAErE4AAAHBXOwUxMGQ18AqheGSg==
+#1 2018-12-18T16:02:30Z pgess
+1sPEAAABsT0AMqdsAAIYEm9sc6JqAQITDEMLQwuDIDODMhMLQ2JDFGMLAJhklUuCMJSIGoM0izSB
+dIJQ
+?>
\ No newline at end of file
diff --git a/documentation/virtualization.xml b/documentation/virtualization.xml
new file mode 100644
index 0000000..8876674
--- /dev/null
+++ b/documentation/virtualization.xml
@@ -0,0 +1,497 @@
+<?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 1k?>
+
+ <title><?xxe-sn 26yv439af40 1l?>Virtualization</title>
+
+ <para><?xxe-sn 26yv439af40 1m?>The chapter expands on a usage of context
+ based polymorphism, in other words, reasoning over CFG, as a ground to
+ implement <emphasis><?xxe-sn 26yv439af40 1n?>application level
+ virtualization</emphasis>.</para>
+
+ <para><?xxe-sn 26yv439af40 1o?>One way to approach virtualization problem is
+ to model it in terms of satisfying constraints imposed by environment over
+ agents that operate within it, as presented below:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 1p?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 1q?>
+
+ <para><?xxe-sn 26yv439af40 1r?><emphasis><?xxe-sn 26yv439af40 1s?>sizo</emphasis>
+ (distorted abbreviation of SEcurity ZOne) — logical entity introduced to
+ represent environment and describe desired virtualization
+ outcome.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 1t?>
+
+ <para><?xxe-sn 26yv439af40 1u?><emphasis><?xxe-sn 26yv439af40 1v?>zek</emphasis>
+ (distorted abbreviation of SEcurity aGent) — represents behaviour of the
+ code in terms of virtualized resources access.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 1w?>Basic idea is to automatically reason over
+ information defined by sizos and zeks and produce <emphasis><?xxe-sn 26yv439af40 1x?>virtualization
+ plan</emphasis> as a solution that dictates which parts of code should be
+ virtualized and how exactly. Such reasoning enables two features:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 1y?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 1z?>
+
+ <para><?xxe-sn 26yv439af40 20?>Optimization. Allows choosing
+ virtualization technique with a least performance penalty nevertheless
+ satisfying necessary requirements.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 21?>
+
+ <para><?xxe-sn 26yv439af40 22?>Safety. Validates manually chosen
+ virtualization plan to be safe and sound by checking that it indeed
+ satisfies requirements.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 23?>In other words, context based reasoning
+ provides improvements by virtualizing only necessary sections of code, only
+ for necessary type of resources and by employing as lightweight as possible
+ virtualization strategy just enough to comply with safety and security
+ requirements expressed by annotations in the code.</para>
+
+ <section>
+ <?xxe-sn 26yv439af40 24?>
+
+ <title><?xxe-sn 26yv439af40 25?>Background</title>
+
+ <para><?xxe-sn 26yv439af40 26?><emphasis><?xxe-sn 26yv439af40 27?>Virtualization</emphasis>
+ refers to an abstracting code from underlying <emphasis><?xxe-sn 26yv439af40 28?>resources</emphasis>
+ used by it. Here term resource depicts any external entity such as
+ devices, files, network connections, etc, for which it is desirable to
+ regulate access.</para>
+
+ <para><?xxe-sn 26yv439af40 29?>Virtualization is a vast area and broad
+ term that includes number of techniques on different levels to achieve
+ several important goals such as:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 2a?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 2b?>
+
+ <para><?xxe-sn 26yv439af40 2c?>Shared access — to allow several
+ clients use the same resource while behaving as if each client is the
+ sole resource user simplifying development and testing.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 2d?>
+
+ <para><?xxe-sn 26yv439af40 2e?>Isolation — cornerstone of safety and
+ behaviour repeatability achieved by minimizing influence of isolated
+ clients between each other and external environment.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 2f?>
+
+ <para><?xxe-sn 26yv439af40 2g?>Adaptation — to allow client
+ application work within an unexpected environment it was not developed
+ for, by emulating "native" familiar environment thus reducing
+ adaptation and support costs.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 2h?>Due to importance of goals achievable with
+ virtualization, it is unavoidable in a long run. That being said, basic
+ virtualization techniques have performance penalties arising from indirect
+ and regulated access to underlying resources.</para>
+
+ <para><?xxe-sn 26yv439af40 2i?>Further discussion is concerned with what
+ can be done to alleviate major virtualization inefficiencies by
+ fine-grained control over what, when, and how should be
+ virtualized.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 2j?>
+
+ <title><?xxe-sn 26yv439af40 2k?>Access Control</title>
+
+ <para><?xxe-sn 26yv439af40 2l?>Whole program can be broken down into one
+ or more virtualization zones, each having different appropriate type of
+ virtualization strategy. Such approach allows to model <emphasis><?xxe-sn 26yv439af40 2m?>hybrid
+ virtualization</emphasis>, i.e. different parts of program are virtualized
+ differently depending on some conditions. To capture this concept, term
+ <emphasis><?xxe-sn 26yv439af40 2n?>sizo</emphasis> is introduced and
+ refers to a logical entity that holds information about particular zone
+ necessary to find best suited virtualization strategy.</para>
+
+ <important>
+ <?xxe-sn 26yv439af40 2o?>
+
+ <para><?xxe-sn 26yv439af40 2p?>Sizo is associated with <link
+ xlink:href="/w/concepts/context"><?xxe-sn 26yv439af40 2q?>context</link>,
+ i.e. each zone spans over one or more code blocks.</para>
+ </important>
+
+ <para><?xxe-sn 26yv439af40 2r?>There is a annotation <code><?xxe-sn 26yv439af40 2s?>assign_sizo</code>
+ to specify sizo a code block is assigned to:</para>
+
+ <synopsis><?xxe-sn 26yv439af40 2t?>SYNTAX:
+**assign_sizo**(//sizo-ref//).</synopsis>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 2u?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 2v?>
+
+ <para><?xxe-sn 26yv439af40 2w?><emphasis><?xxe-sn 26yv439af40 2x?>sizo-ref</emphasis>
+ unique sizo's identifier</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 2y?>Next thing is to specify which resources a
+ particular sizo controls access to, as below:</para>
+
+ <synopsis><?xxe-sn 26yv439af40 2z?>SYNTAX:
+**assign_sizo_control**(//resource-type//).</synopsis>
+
+ <para><?xxe-sn 26yv439af40 30?>It indicates that current sizo(sizo that
+ spans over code block the annotation located within) regulates all access
+ to a resources of a given type <emphasis><?xxe-sn 26yv439af40 31?>resource-type</emphasis>.
+ Conversely, If for a particular environment there is no need to control,
+ for example, file system access, no virtualization for file operations is
+ applied.</para>
+
+ <para><?xxe-sn 26yv439af40 32?>On the other hand, there is an annotation
+ to mark function that accesses one or another resource:</para>
+
+ <synopsis><?xxe-sn 26yv439af40 33?>SYNTAX:
+**assign_zek_access**(//resource-type//).</synopsis>
+
+ <para><?xxe-sn 26yv439af40 34?>Let's consider an example to demonstrate
+ all above:</para>
+
+ <programlisting xml:id="AccControl_1"><?xxe-sn 26yv439af40 35?>name="tests/virtualization.cpp: Virtualization.Doc_AccControl_1", lines=15
+import raw ("scripts/cfa/context.lp"). //enable context reasoning
+import raw ("scripts/virtualization/virtualization.lp"). //enable virtualization reasoning
+
+guard:: strategy(direct)
+{
+ openFile = function(filename::string):: int
+ {
+ printf("direct file access")
+ }
+}
+
+guard:: strategy(common)
+{
+ openFile = function(filename::string):: int;
+ assign_zek_access(files)
+ {
+ printf("virtualized file access")
+ }
+}
+
+main = function:: int; entry
+{
+ context:: assign_sizo(zoneA);
+ assign_sizo_control(files).
+ openFile("/some/file")
+}</programlisting>
+
+ <para><?xxe-sn 26yv439af40 36?>Example outlines dummy function
+ <code><?xxe-sn 26yv439af40 37?>openFile</code> to model file system
+ access. The function has two specializations with guards <code><?xxe-sn 26yv439af40 38?>strategy(direct)</code>
+ to model direct access, and <code><?xxe-sn 26yv439af40 39?>strategy(common)</code>
+ to be invoked if virtualization is enabled. It also annotated with
+ <code><?xxe-sn 26yv439af40 3a?>assign_zek_access(files)</code> to indicate
+ that it accesses file system. On the other hand, context of function
+ <code><?xxe-sn 26yv439af40 3b?>main</code> defines sizo <code><?xxe-sn 26yv439af40 3c?>zoneA</code>
+ and enables control over file operations.</para>
+
+ <para><?xxe-sn 26yv439af40 3d?>Reasoning works with provided information
+ and decides whether it is necessary to enable virtualization. In this
+ case, the answer is yes for <code><?xxe-sn 26yv439af40 3e?>zoneA</code>,
+ because of the fact that sizo controls file operations and there is
+ actually function within the sizo that requires files access.
+ Consequently, example outputs:<screen xml:id="Output_AccControl_1"><?xxe-sn 26yv439af40 3f?>virtualized file access</screen>confirming
+ that specifically virtualized specialization of <code><?xxe-sn 26yv439af40 3g?>openFile</code>
+ was invoked.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 3h?>
+
+ <title><?xxe-sn 26yv439af40 3i?>Isolation</title>
+
+ <para><?xxe-sn 26yv439af40 3j?>As shown in the previous section, it is
+ possible to enable(or disable) virtualization on per resource basis.
+ However such functionality is limited in a sense that if several sizos
+ allow access to the same resource they can interfere with each other.
+ Thus, next step to consider is <emphasis><?xxe-sn 26yv439af40 3k?>isolation</emphasis>,
+ i.e. zeks in different sizos should not have ability to access the same
+ resource, but rather work with their own set of resources associated with
+ particular sizo. As previously, following examples are focused on file
+ operations as most ubiquitous type of resources.</para>
+
+ <para><?xxe-sn 26yv439af40 3l?>One way to isolate file access is to
+ associate unique file prefix with each sizo. If virtualization enabled,
+ all filenames in the sizo are silently transformed on the fly by adding
+ assigned prefix. This way, all the file operations from one sizo are
+ confined within specific directory allocated solely for that particular
+ sizo or simply have unique prefix if the same directory contains files
+ belonging to a different sizos.</para>
+
+ <programlisting xml:id="Isolation_1"><?xxe-sn 26yv439af40 3m?>name="tests/virtualization.cpp: Doc_Isolation_1", lines=15
+main = function:: int; entry
+{
+ seq
+ {
+ context:: assign_sizo(domainA);
+ assign_sizo_control(files).
+ openFile("test")
+ }
+ {
+ context:: assign_sizo(domainA).
+
+ openFile("test")
+ }
+ {
+ context:: assign_sizo(domainB);
+ assign_sizo_control(files).
+ openFile("test")
+ }
+}</programlisting>
+
+ <para><?xxe-sn 26yv439af40 3n?>In this example file <code><?xxe-sn 26yv439af40 3o?>test</code>
+ is accessed from different sizos <code><?xxe-sn 26yv439af40 3p?>domainA</code>
+ and <code><?xxe-sn 26yv439af40 3q?>domanB</code>. As there are several
+ "competing" sizos are declared, they are isolated and <code><?xxe-sn 26yv439af40 3r?>openFile</code>
+ resolves <code><?xxe-sn 26yv439af40 3s?>test</code> to a different
+ filename depending on from which sizo it is called. One possible way to
+ implement discussed strategy shown below:</para>
+
+ <programlisting xml:id="Isolation_2"><?xxe-sn 26yv439af40 3t?>name="tests/virtualization.cpp: Doc_Isolation_1", lines=15
+import raw ("scripts/cfa/context.lp"). //enable context reasoning
+import raw ("scripts/virtualization/virtualization.lp"). //enable virtualization reasoning
+import raw ("scripts/virtualization/test-Isolation_1.assembly.lp"). //additional configuration
+
+DictSizo = type slave dict_sizo.
+Sizo = type slave virt_sizo.
+
+guard:: strategy(direct)
+{
+ resolveFilename = function(filename:: string):: string;
+ assign_zek_access(files)
+ {
+ filename
+ }
+}
+
+guard:: strategy(prefix)
+{
+ resolveFilename = function(filename:: string):: string;
+ assign_zek_access(files)
+ {
+ dictSizo = intrinsic query("dict_sizo")::[DictSizo].
+ sizoId = intrinsic query late("sizo_current"-&gt;sizoCurrent:: Sizo):: int;
+ demand(sizo)
+ {
+ loop fold(dictSizo-&gt;entry::DictSizo, 0-&gt;id):: int
+ {
+ if(entry[0] == sizoCurrent):: int { entry[1] } else { id }
+ }
+ }.
+
+ buf = "00"::string.
+ seq
+ { sprintf(buf, "%d/%s", sizoId, filename) }
+ { buf }
+ }
+}
+
+openFile = function(filename:: string):: int
+{
+ filenameReal = resolveFilename(filename):: string.
+ printf("File opened: '%s'%c", filenameReal, 10)
+}</programlisting>
+
+ <para><?xxe-sn 26yv439af40 3u?>Example outputs:</para>
+
+ <screen xml:id="Output_Isolation_1"><?xxe-sn 26yv439af40 3v?>File opened: '0/test'
+File opened: '0/test'
+File opened: '1/test'
+</screen>
+
+ <para><?xxe-sn 26yv439af40 3w?>In this example function <code><?xxe-sn 26yv439af40 3x?>openFile</code>
+ calls <code><?xxe-sn 26yv439af40 3y?>resolveFilename</code> to find out
+ real filename. It can be said, that <code><?xxe-sn 26yv439af40 3z?>resolveFilername</code>
+ serves as <emphasis><?xxe-sn 26yv439af40 40?>hypervisor</emphasis>
+ dereferencing file pseudonym into real filename. In order to do that,
+ <code><?xxe-sn 26yv439af40 41?>resolveFilername</code> consists of two
+ specializations: specialization <code><?xxe-sn 26yv439af40 42?>strategy(direct)</code>
+ serves non virtualized environmentб leaving filename without any
+ processing, and the other specialization <code><?xxe-sn 26yv439af40 43?>strategy(prefix)</code>
+ implements resolving strategy by adding sizo-associated prefix to each
+ file. More specifically, unique index is assigned to each sizo and
+ <code><?xxe-sn 26yv439af40 44?>resolveFilename</code> uses the index as
+ file name prefix.</para>
+
+ <para><?xxe-sn 26yv439af40 45?>Resolution function <code><?xxe-sn 26yv439af40 46?>resolveFilename</code>
+ has only one parameter <code><?xxe-sn 26yv439af40 47?>filename</code>,
+ deriving required prefix from <emphasis><?xxe-sn 26yv439af40 48?>late
+ context</emphasis> associated with particular sizo.</para>
+
+ <important>
+ <?xxe-sn 26yv439af40 49?>
+
+ <para><?xxe-sn 26yv439af40 4a?>Client code has no way to influence
+ resolving process and force to use unapproved prefix, thus accessing and
+ interfering with files that belong to other sizos.</para>
+ </important>
+ </section>
+
+ <section>
+ <?xxe-sn 26yv439af40 4b?>
+
+ <title><?xxe-sn 26yv439af40 4c?>Isolation Categories</title>
+
+ <para><?xxe-sn 26yv439af40 4d?>Every optimization technique applicable
+ only if some specific preconditions are met. Indeed, only general approach
+ can handle general task. However, for practical instances there are always
+ some improvements possible by tailoring to the particular use case
+ specifics and subtle details. In other words, the more information
+ available the more space for improvements is there. And first step on this
+ road is the very ability to express and reason about such additional
+ information.</para>
+
+ <para><?xxe-sn 26yv439af40 4e?>As a demonstration, in order to improve
+ reasoning to find out optimal virtualization strategy for particular use
+ case, different <emphasis><?xxe-sn 26yv439af40 4f?>sizo
+ categories</emphasis> can be introduced, as below:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 4g?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 4h?>
+
+ <para><?xxe-sn 26yv439af40 4i?><emphasis><?xxe-sn 26yv439af40 4j?>Inward
+ Isolation</emphasis>. The category describes sizo that prohibits
+ access from other sizos to its internal resources, but able to access
+ external resources freely. For example, monitoring and supervision
+ software may have been assigned this type of isolation — freely
+ accesses subordinate zones but can't be influenced from the
+ outside.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 4k?>
+
+ <para><?xxe-sn 26yv439af40 4l?><emphasis><?xxe-sn 26yv439af40 4m?>Outward
+ isolation</emphasis>. The exact opposite of inward isolation. Allows
+ access from external sizos but is only allowed to use its own internal
+ resources, so no influence to the outside world is possible.
+ Appropriate for various sandboxes and testing environments to run
+ possibly insecure code.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 4n?>For file operations inward isolation may be
+ implemented as virtualization strategy that requires from
+ <emphasis><?xxe-sn 26yv439af40 4o?>other</emphasis> sizos compulsory usage
+ of file prefixes so no other sizo can access internal data of inwardly
+ isolated sizo. Conversely, outward isolation is compatible with strategy
+ that assigns prefix for this very sizo, so it can in no way access any
+ external data, being at the same time exposed to the outside world for any
+ sizo that have permission to know unique assigned prefix able to access
+ internal data of sizo in question. To put it simply, strategy for these
+ types can be described with following points:</para>
+
+ <itemizedlist>
+ <?xxe-sn 26yv439af40 4p?>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 4q?>
+
+ <para><?xxe-sn 26yv439af40 4r?>Inward isolation — requires prefixes
+ for other sizos.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 26yv439af40 4s?>
+
+ <para><?xxe-sn 26yv439af40 4t?>Outward isolation — requires prefix for
+ itself.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 26yv439af40 4u?>There is an annotation introduced to
+ declare category for the current sizo:</para>
+
+ <synopsis><?xxe-sn 26yv439af40 4v?>SYNTAX:
+**assign_sizo_category(inward)**.
+**assign_sizo_category(outward)**.</synopsis>
+
+ <para><?xxe-sn 26yv439af40 4w?>Consider the example below:</para>
+
+ <programlisting xml:id="IsolationCat_1"><?xxe-sn 26yv439af40 4x?>name="tests/virtualization.cpp: Doc_IsolationCat_1", lines=15
+test = function:: int; entry
+{
+ seq
+ {
+ context:: assign_sizo(zoneA);
+ assign_sizo_control(files);
+ assign_sizo_category(inward).
+ openFile("test1")
+ }
+ {
+ context:: assign_sizo(zoneB);
+ assign_sizo_control(files);
+ assign_sizo_category(outward).
+ openFile("test1")
+ }
+}
+</programlisting>
+
+ <para><?xxe-sn 26yv439af40 4y?>There are two sizos declared in the code
+ above. Using reasoning apparatus developed in previous sections, both
+ sizos activate virtualization, for both of them control file resources and
+ both contain <code><?xxe-sn 26yv439af40 4z?>openFile</code> that actually
+ requires file access. However, this time additional bits of information
+ are available, namely <code><?xxe-sn 26yv439af40 50?>zoneA</code> and
+ <code><?xxe-sn 26yv439af40 51?>zoneB</code> declared as inward and
+ outward, respectively. By strategy outlines above, <code><?xxe-sn 26yv439af40 52?>zoneA</code>
+ enables prefix based isolation strategy for <code><?xxe-sn 26yv439af40 53?>zoneB</code>,
+ and <code><?xxe-sn 26yv439af40 54?>zoneB</code> enables isolation for
+ itself as well. As a result, it's enough to virtualize only one
+ zone(<code><?xxe-sn 26yv439af40 55?>zoneB</code>) leaving <code><?xxe-sn 26yv439af40 56?>zoneA</code>
+ to enjoy direct access to file resources. Example output's is shown below,
+ confirming that direct file access is granted for <code><?xxe-sn 26yv439af40 57?>zoneA</code>:</para>
+
+ <screen xml:id="Output_IsolationCat_1"><?xxe-sn 26yv439af40 58?>File opened: 'test1'
+File opened: '1/test1'
+</screen>
+ </section>
+</chapter>
+<?xxe-revisions
+#1 2018-12-18T13:45:06Z pgess
+?>
\ No newline at end of file
diff --git a/scripts/cfa/context.lp b/scripts/cfa/context.lp
index f97d57a..0543063 100644
--- a/scripts/cfa/context.lp
+++ b/scripts/cfa/context.lp
@@ -1,106 +1,105 @@
% 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/.
%% INPUT:
%% - latex_scope_demand(Scope, Subject)
%% Initial demand from clients
%%
%% - latex_registered_subjects(Subject, PossibleDecision)
%% Clients register possible decisions for respective subjects
%%
%% - latex_fn_signature
%%
%% OUTPUT:
%% - latex_fn_demand(Fn, Subject)
%% Which functions demand hidden latex arguments
%%
%% - latex_decision(Scope, Subject, Decision)
%% Provided decisions, values for hidden latex arguments
%%
%% SIGNATURES:
%% -Subject: string
%%
% CONTEXT PROPAGATION
%===========================================================
% nested scope propagation:
bind_scope(Scope, Context, Info):-
bind_scope(ScopeParent, Context, Info);
cfa_parent(Scope, scope(ScopeParent)).
% Strong or Uniform inter-function propagation:
bind_scope(Scope, Context, Info):-
bind_scope(ScopeParent, Context, Info): cfa_call(ScopeParent, FnCurrent);
cfa_parent(Scope, function(FnCurrent)); cfa_call(_, FnCurrent);
bind_scope(_, Context, Info); scope(Scope).
% weak inter-function propagation
bind_scope(Scope, Context, weak(ScopeParent)):-
not bind_scope(Scope, Context, strong);
bind_scope(ScopeParent, Context, strong);
cfa_call(ScopeParent, FnCurrent);
cfa_parent(Scope, function(FnCurrent)).
% DEMAND
%===========================================================
%demand propagations: scope level
latex_scope_demand(Scope, Subject):-
latex_scope_demand(ScopeChild, Subject);
cfa_parent(ScopeChild, scope(Scope)).
%propagation: fn level
latex_fn_demand(Fn, Subject):-
latex_scope_demand(ScopeFnBody, Subject);
cfa_parent(ScopeFnBody, function(Fn)).
latex_fn_demand_ordered(Fn, Subject, Id):-
Id= #sum{ 1, SubjLess : latex_fn_demand(Fn, SubjLess), SubjLess < Subject};
latex_fn_demand(Fn, Subject).
%propagation: inter-fn level
latex_scope_demand(Scope, Subject):-
latex_fn_demand(FnCallee, Subject);
not latex_decision(Scope, Subject, _);
cfa_call(Scope, FnCallee).
% DECISIONS
%===========================================================
latex_decision(Scope, Subject, Decision):-
latex_fn_demand(FnCallee, Subject);
bind_scope(Scope, Decision, strong);
cfa_call(Scope, FnCallee);
latex_registered_subjects(Subject, Decision).
%late decision
late((ScopeCaller, Subject), SubjectS, (AnyDecision), latex_decision(ScopeCaller, Subject, AnyDecision)):-
- scope_fn(ScopeCaller, FnCaller);
- cfa_parent(FnCallerBody, function(FnCaller));
- latex_symbol(FnCaller, Subject, SubjectS);
+ scope_fnbody(ScopeCaller, FnCallerBody);
+ latex_symbol(FnCallerBody, Subject, SubjectS);
cfa_call(ScopeCaller, FnCallee);
latex_fn_demand(FnCallee, Subject);
latex_registered_subjects(Subject, AnyDecision).
% UTILITY
%===========================================================
-latex_symbol(Fn, Topic, s(TopicsOffset + TopicId, -2, FnBody)):-
+latex_symbol(FnBody, Topic, s(TopicsOffset + TopicId, -2, FnBody)):-
cfa_parent(FnBody, function(Fn));
latex_parameters_offset(TopicsOffset);
latex_fn_demand_ordered(Fn, Topic, TopicId).
% IMPLEMENTATION
%===========================================================
-scope_fn(Scope, Fn):-cfa_parent(Scope, function(Fn)).
-scope_fn(Scope, Fn):-
- scope_fn(ScopeParent, Fn);
+scope_fnbody(Scope, Scope):-cfa_parent(Scope, function(_)).
+scope_fnbody(Scope, FnBody):-
+ scope_fnbody(ScopeParent, FnBody);
cfa_parent(Scope, scope(ScopeParent)).
latex_parameters_offset(1000).
diff --git a/scripts/cfa/payload.lp b/scripts/cfa/payload.lp
new file mode 100644
index 0000000..99662e1
--- /dev/null
+++ b/scripts/cfa/payload.lp
@@ -0,0 +1,68 @@
+%cfa_seq(From, To)
+%cfa_payload(X, Node, Path)
+
+ %EXTERNAL CALL
+ %constraints: fn's entry/final scope does not have prev/next scopes resp.
+:- cfa_seq_guarded(_, NodeTo, in(_)); cfa_seq(_, NodeTo).
+:- cfa_seq_guarded(NodeFrom, _, out(_)); cfa_seq(NodeFrom, _).
+
+cfa_payload(P, NodeTo, (Guard, Path)):-
+ cfa_payload(P, NodeFrom, Path);
+ cfa_seq_guarded(NodeFrom, NodeTo, in(Guard)).
+
+weak(cfa_payload(P, NodeTo, (Guard, Path))):-
+ weak(cfa_payload(P, NodeFrom, Path));
+ cfa_seq_guarded(NodeFrom, NodeTo, in(Guard)).
+
+ %Path collapse
+cfa_payload(P, Node, Path):-
+ cfa_payload(P, NodeFrom, Path) : cfa_seq_guarded(NodeFrom, Node, in(_));
+ cfa_payload(P, Node, (_, Path));
+ cfa_seq_guarded(_, Node, in(_)).
+
+ %EXTERNAL RET
+cfa_payload(P, NodeTo, Path2):-
+ cfa_payload(P, NodeFrom, Path); Path = (Guard, Path2);
+ cfa_seq_guarded(NodeFrom, NodeTo, out(Guard)).
+
+cfa_payload(P, NodeTo, ()):-
+ cfa_payload(P, NodeFrom, ());
+ cfa_seq_guarded(NodeFrom, NodeTo, out(_)).
+
+weak(cfa_payload(P, NodeTo, Path2)):-
+ weak(cfa_payload(P, NodeFrom, Path)); Path = (Guard, Path2);
+ cfa_seq_guarded(NodeFrom, NodeTo, out(Guard)).
+
+ %INTERNAL
+weak(cfa_payload(P, Node, Path)):-
+ weak(cfa_payload(P, NodeFrom, Path));
+ cfa_seq(NodeFrom, Node).
+
+ %INTERNAL AND
+cfa_payload(P, Node, Path):-
+ cfa_payload(P, NodeFrom, Path);
+ cfa_seq(NodeFrom, Node); Node = and(_).
+
+
+ %INTERNAL OR
+weak(cfa_payload(P, Node, Path)):-
+ cfa_payload(P, NodeFrom, Path);
+ cfa_seq(NodeFrom, Node); Node = or(_).
+
+cfa_payload(P, Node, Path):-
+ cfa_payload(P, NodeFrom, Path) : cfa_seq(NodeFrom, Node);
+ Node = or(_);
+ cfa_seq(N, Node); cfa_payload(P, N, Path).
+
+ %INTERNAL EMPTY
+ %INTERNAL SCOPE
+:- cfa_seq(A, empty(X)); cfa_seq(B, empty(X)); A<>B.
+:- cfa_seq(A, scope(X)); cfa_seq(B, scope(X)); A<>B.
+
+cfa_payload(P, Node, Path):-
+ cfa_payload(P, NodeFrom, Path);
+ cfa_seq(NodeFrom, Node); Node = empty(_).
+
+cfa_payload(P, Node, Path):-
+ cfa_payload(P, NodeFrom, Path);
+ cfa_seq(NodeFrom, Node); Node = scope(_).
diff --git a/scripts/exploitation/exploitation.lp b/scripts/exploitation/exploitation.lp
index d4643a3..fc4d7ee 100644
--- a/scripts/exploitation/exploitation.lp
+++ b/scripts/exploitation/exploitation.lp
@@ -1,86 +1,24 @@
-% INPUT:
-% cfa: cfa_forwdom
-% expl_siteUser(Resource, UserScope), expl_siteInit(Resource, ScopeInit)
-%
-
-
-% PARTITION
-%=============================================================
-expl_mutual_dom(UserScope1, UserScope2, DomHighest):-
- Ahighest = #max{ AD, (AD, BD): cfa_forwdom(Dom, range(AD, BD)), AD<A1, AD<A2, BD > B1, BD > B2};
- cfa_forwdom(DomHighest, range(Ahighest, _));
- cfa_forwdom(UserScope1, range(A1, B1));
- cfa_forwdom(UserScope2, range(A2, B2));
- UserScope1<UserScope2; UserScope1!=null; UserScope2!=null; DomHighest!=null.
-
-expl_partition(Resource, UserScope1, UserScope2, Dom):-
- expl_mutual_dom(UserScope1, UserScope2, Dom);
- expl_siteUser(Resource, UserScope1); expl_siteUser(Resource, UserScope2); UserScope1<UserScope2.
-
-expl_partition_root(Resource, User):-
- expl_siteUser(Resource, User);
- not expl_partition(Resource, _, User, _).
-
-expl_partition_dom(Resource, UserRoot, DomHighest ):-
- Ahighest = #max{A1, (A1, B1):expl_partition(Resource, UserRoot, _, Dom), cfa_forwdom(Dom, range(A1, B1))};
- cfa_forwdom(DomHighest, range(Ahighest, _));
- expl_partition_root(Resource, UserRoot).
-
-expl_partition_dom(Resource, UserRoot, DomHighest ):-
- Ahighest = #max{AD, (AD, BD): cfa_forwdom(Dom, range(AD, BD)), AD<A1, BD>B1};
- cfa_forwdom(DomHighest, range(Ahighest, _));
- cfa_forwdom(UserRoot, range(A1, B1));
- not expl_partition(Resource, UserRoot, _, _);
- expl_partition_root(Resource, UserRoot).
-
-expl_init_assignments(Resource, SiteInitAssigned):-
- A_Highest = #max{AI, (AI, BI): expl_siteInit(Resource, SiteI), cfa_forwdom(SiteI, range(AI, BI))};
- cfa_forwdom(SiteInitAssigned, range(A_Highest, _));
- expl_partition_root(Resource, _).
-
-% SOLUTIONS
-%=============================================================
-
-
-% ORDER
-%=============================================================
-
+%DOMINATOR ANALYSIS BASED ON PAYLOAD
+%===========================================================
+cfa_payload(expl_siteInit(Resource, Scope), scope(Scope), ()):-
+ expl_siteInit(Resource, Scope).
-% Doms/PostDom trees
-%=============================================================
-%cfa_forwdom
-
-
-% LANDSCAPE
-%=============================================================
-%expl_landscape(X, )
-
-
-% GARBAGE
-%=============================================================
-%expl_parent(Site, Parent):-
-% A<A1; B1<B;
-% cfa_forwdom(Parent, range(A, B));
-% cfa_forwdom(Site, range(A1, B1)).
-
-%expl_parent(Site, postdom(Parent)):-
-% A<A1; B1<B;
-% cfa_postdom(Parent, range(A, B));
-% cfa_postdom(Site, range(A1, B1)).
-
-%epxl_impl(Site, Resource, direct):-
-% expl_siteUser(Site, Resource);
-% expl_siteInit(SiteParent, Resource);
-% expl_parent(Site, SiteParent).
-
-%expl_impl(Site, Resource, direct):-
-% expl_siteUser(Site, Resource);
-% expl_initAccepted(SiteInit, Resource);
-% expl_deinitAccepted(SiteDeinit, Resource);
-
-%expl_order(S1, S2):- cfa_scope_depends(S1,S2).
-%expl_order(S1, S3):-
-% cfa_parent(S1, S2);
-% expl_order(S2, S3);
-% not cfa_scope_depends(S1,_).
+expl_supdom(Resource, Scope):-
+ cfa_payload(expl_siteInit(Resource, Scope), scope(Scope), ());
+ cfa_payload(expl_siteInit(Resource, ScopeSup), scope(ScopeSup), ());
+ not cfa_payload(expl_siteInit(Resource, ScopeSup), scope(Scope), ());
+ ScopeSup <> Scope.
+
+
+%ASSIGNMENTS
+%===========================================================
+
+expl_assignments(Init, Resource, init):-
+ expl_siteUser(Resource, User);
+ cfa_payload(expl_siteInit(Resource, Init), scope(User), ());
+ expl_supdom(Resource, Init).
+
+expl_assignments(Init, Resource, none):-
+ expl_siteInit(Resource, Init);
+ not expl_assignments(Init, Resource, init).
diff --git a/scripts/exploitation/test1.assembly.lp b/scripts/exploitation/test1.assembly.lp
index 7fcdb32..21efa4f 100644
--- a/scripts/exploitation/test1.assembly.lp
+++ b/scripts/exploitation/test1.assembly.lp
@@ -1,27 +1,24 @@
-% INPUT
+% Connect to Exploitation
%===========================================================
-expl_siteUser(Res, Scope):-
- dictVarScope(Var, Scope);
- bind(Var, expl_user(Res)).
+expl_siteInit(Resource, CallerS):-
+ bind_func(Fn, init(Resource));
+ cfa_call(CallerS, Fn).
-expl_siteInit(Res, Scope):-
- dictVarScope(Var, Scope);
- bind(Var, expl_init(Res)).
+expl_siteUser(Resource, Scope):-
+ bind(V, use(Resource));
+ var_scope(V, Scope).
-% OUTPUT
+% Connect to Polymorphism
%===========================================================
-dfa_callguard(Var, explInitRealImpl):-
- expl_init_assignments(Res, SiteInitAssigned);
- bind(Var, expl_init(Res));
- dictVarScope(Var, SiteInitAssigned).
-
-dfa_callguard(Var, explInitBogusImpl):-
- not expl_init_assignments(Res, SiteInit);
- bind(Var, expl_init(Res));
- dictVarScope(Var, SiteInit).
+dfa_callguard(V, exploitation(Strategy)):-
+ expl_assignments(Scope, Resource, Strategy);
+ dfa_callfn(V, Fn);
+ bind_func(Fn, init(Resource));
+ var_scope(V, Scope).
+
-% GENERAL
+% Utility
%===========================================================
-dictVarScope(Var, Scope):- Var=s(_, _, Scope); v(Var).
+var_scope(Var, Scope):- Var=s(_, _, Scope); v(Var).
diff --git a/scripts/exploitation/test1.xreate b/scripts/exploitation/test1.xreate
index 75dc1a5..4406768 100644
--- a/scripts/exploitation/test1.xreate
+++ b/scripts/exploitation/test1.xreate
@@ -1,32 +1,9 @@
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = {"scripts/exploitation/test1.h"}
}.
}
-import raw ("scripts/exploitation/exploitation.lp").
-import raw ("scripts/exploitation/test1.assembly.lp").
-
-guard:: explInitRealImpl {
- openFile = function(filePrev:: FILE_P):: FILE_P {
- fopen("/tmp/test", "w")::FILE_P
- }
-}
-
-guard:: explInitBogusImpl {
- openFile = function(filePrev:: FILE_P):: FILE_P {
- filePrev::int
- }
-}
-
-test = function::int; entry {
- seq
- { f0 = undef:: FILE_P. f0 }
- { f1 = openFile(f0):: FILE_P; expl_init(r1). f1 /*first attempt to open file*/}
- { f2 = openFile(f1):: FILE_P; expl_init(r1). f2 /*second attempt to open file*/}
- { sizeWritten = fwrite("WriteAttempt", 12, 1, f2):: int; expl_user(r1). sizeWritten }
- { fclose(f2)::int; expl_use(r1)}
- { sizeWritten :: int}
-}
+<BODY>
diff --git a/scripts/virtualization/test1.h b/scripts/virtualization/defs.h
similarity index 100%
rename from scripts/virtualization/test1.h
rename to scripts/virtualization/defs.h
diff --git a/scripts/virtualization/test-AccControl_1.xreate b/scripts/virtualization/test-AccControl_1.xreate
new file mode 100644
index 0000000..32bd0a0
--- /dev/null
+++ b/scripts/virtualization/test-AccControl_1.xreate
@@ -0,0 +1,9 @@
+interface(extern-c){
+ externalLibs = library:: pkgconfig("libxml-2.0").
+
+ include {
+ externalLibs = {"scripts/virtualization/defs.h"}
+ }.
+}
+
+<BODY>
diff --git a/scripts/virtualization/test-IsolationCat_1.assembly.lp b/scripts/virtualization/test-IsolationCat_1.assembly.lp
new file mode 100644
index 0000000..a11434c
--- /dev/null
+++ b/scripts/virtualization/test-IsolationCat_1.assembly.lp
@@ -0,0 +1,40 @@
+% Register late query for `sizo_current`
+%-----------------------------------
+late(Target, SymbolSizo, (SizoAny), sizo_current(SizoAny)):-
+ bind(Target, demand(sizo));
+ Target=s(_, _, TargetS);
+ scope_fnbody(TargetS, FnBody);
+ latex_symbol(FnBody, sizo, SymbolSizo);
+ virt_sizo(SizoAny).
+
+
+% Categories Reasoning
+%=========================================================== .
+virt_sizo_category(Sizo, Category):-
+ bind_scope(Scope, assign_sizo_category(Category), strong);
+ bind_scope(Scope, assign_sizo(Sizo), strong);
+ virt_sizo(Sizo).
+
+2{
+ virt_sizo_strategy(SizoOther, files, prefix);
+ decided(virt_strategy(SizoOther, files), 3;2)
+}:-
+ virt_sizo_control(SizoSelf, files);
+ virt_sizo_category(SizoSelf, inward);
+
+ virt_sizo_control(SizoOther, files);
+ SizoOther <> SizoSelf.
+
+2{
+ virt_sizo_strategy(SizoSelf, files, prefix);
+ decided(virt_strategy(SizoSelf, files), 3;2)
+}:-
+ virt_sizo_control(SizoSelf, files);
+ virt_sizo_category(SizoSelf, outward).
+
+2{
+ virt_sizo_strategy(Sizo, files, direct);
+ decided(virt_strategy(Sizo, files), 2)
+}:-
+ virt_sizo_control(Sizo, files);
+ not decided(virt_strategy(Sizo, files), 3).
diff --git a/scripts/virtualization/test-IsolationCat_1.xreate b/scripts/virtualization/test-IsolationCat_1.xreate
new file mode 100644
index 0000000..df32737
--- /dev/null
+++ b/scripts/virtualization/test-IsolationCat_1.xreate
@@ -0,0 +1,53 @@
+interface(extern-c){
+ externalLibs = library:: pkgconfig("libxml-2.0").
+
+ include {
+ externalLibs = {"scripts/virtualization/defs.h"}
+ }.
+}
+
+import raw ("scripts/cfa/context.lp"). //enable context reasoning
+import raw ("scripts/virtualization/virtualization.lp"). //enable virtualization reasoning
+import raw ("scripts/virtualization/test-IsolationCat_1.assembly.lp"). //additional configuration
+
+DictSizo = type slave dict_sizo.
+Sizo = type slave virt_sizo.
+
+guard:: strategy(direct)
+{
+ resolveFilename = function(filename:: string):: string;
+ assign_zek_access(files)
+ {
+ filename
+ }
+}
+
+guard:: strategy(prefix)
+{
+ resolveFilename = function(filename:: string):: string;
+ assign_zek_access(files)
+ {
+ dictSizo = intrinsic query("dict_sizo")::[DictSizo].
+ sizoId = intrinsic query late("sizo_current"->sizoCurrent:: Sizo):: int;
+ demand(sizo)
+ {
+ loop fold(dictSizo->entry::DictSizo, 0->id):: int
+ {
+ if(entry[0] == sizoCurrent):: int { entry[1] } else { id }
+ }
+ }.
+
+ buf = "00"::string.
+ seq
+ { sprintf(buf, "%d/%s", sizoId, filename) }
+ { buf }
+ }
+}
+
+openFile = function(filename:: string):: int
+{
+ filenameReal = resolveFilename(filename):: string.
+ printf("File opened: '%s'%c", filenameReal, 10)
+}
+
+<EXAMPLE>
diff --git a/scripts/virtualization/test-Isolation_1.assembly.lp b/scripts/virtualization/test-Isolation_1.assembly.lp
new file mode 100644
index 0000000..908391e
--- /dev/null
+++ b/scripts/virtualization/test-Isolation_1.assembly.lp
@@ -0,0 +1,8 @@
+% Register late query for `sizo_current`
+%-----------------------------------
+late(Target, SymbolSizo, (SizoAny), sizo_current(SizoAny)):-
+ bind(Target, demand(sizo));
+ Target=s(_, _, TargetS);
+ scope_fnbody(TargetS, FnBody);
+ latex_symbol(FnBody, sizo, SymbolSizo);
+ virt_sizo(SizoAny).
diff --git a/scripts/virtualization/test-Isolation_1.xreate b/scripts/virtualization/test-Isolation_1.xreate
new file mode 100644
index 0000000..4fe8fae
--- /dev/null
+++ b/scripts/virtualization/test-Isolation_1.xreate
@@ -0,0 +1,10 @@
+interface(extern-c){
+ externalLibs = library:: pkgconfig("libxml-2.0").
+
+ include {
+ externalLibs = {"scripts/virtualization/defs.h"}
+ }.
+}
+
+<PART-B-BODY>
+<PART-A-BODY>
diff --git a/scripts/virtualization/test1.assembly.lp b/scripts/virtualization/test1.assembly.lp
deleted file mode 100644
index 91f2ae1..0000000
--- a/scripts/virtualization/test1.assembly.lp
+++ /dev/null
@@ -1,35 +0,0 @@
-% INPUT
-%-----------------------------------
-% sizo(..).
-
-sizo(Sizo):-
- bind_scope(_, attachedSizo(Sizo), strong).
-
-dict_sizo(Sizo, Id):-
- Id= #sum{ 1, SizoLess : sizo(SizoLess), SizoLess < Sizo};
- sizo(Sizo).
-
-% connect to latex
-%-----------------------------------
-latex_registered_subjects(sizo, Sizo):- sizo(Sizo).
-
-latex_scope_demand(ScopeDemandSizo, sizo):-
- bind(Target, demand(sizo));
- Target = s(_, _, ScopeDemandSizo).
-
-bind_scope(Scope, Sizo, strong):-
- bind_scope(Scope, attachedSizo(Sizo), strong).
-
-% register late query
-%-----------------------------------
-late(Target, SymbolSizo, (SizoAny), sizo_current(SizoAny)):-
- bind(Target, demand(sizo));
- Target=s(_, _, TargetS);
- scope_fn(TargetS, Fn);
- cfa_parent(FnBody, function(Fn));
- latex_symbol(Fn, sizo, SymbolSizo);
- sizo(SizoAny).
-
-
-% IMPLEMENTATION
-%=========================================================== .
diff --git a/scripts/virtualization/test1.xreate b/scripts/virtualization/test1.xreate
deleted file mode 100644
index 3ad7ce8..0000000
--- a/scripts/virtualization/test1.xreate
+++ /dev/null
@@ -1,47 +0,0 @@
-interface(extern-c){
- externalLibs = library:: pkgconfig("libxml-2.0").
-
- include {
- externalLibs = {"scripts/virtualization/test1.h"}
- }.
-}
-
-import raw ("scripts/virtualization/test1.assembly.lp").
-import raw ("scripts/cfa/context.lp").
-
-DictSizo = type slave dict_sizo.
-Sizo = type slave sizo.
-
-virt_getPrefix = function:: string
-{
- dictSizo = intrinsic query("dict_sizo")::[DictSizo].
-
- sizoId = intrinsic query late("sizo_current"->sizoCurrent:: Sizo):: int; demand(sizo)
- {
- loop fold(dictSizo->entry::DictSizo, 0->id):: int {
- if(entry[0] == sizoCurrent):: int { entry[1] } else { id }
- }
- }.
-
- buf = "000000000"::string.
- seq
- { sprintf(buf, "%d", sizoId) }
- { buf }
-}
-
-openFile = function(filename::string):: int
-{
- buf = "0000000000":: string.
- prefix = virt_getPrefix():: string.
- seq
- {sprintf(buf, "/%s/%s", prefix, filename)}
- {printf("file opened: %s ", buf)}
-}
-
-main = function:: int; entry
-{
- seq
- { context::attachedSizo(domainA). openFile("test1") }
- { context::attachedSizo(domainB). openFile("test1") }
- { 0 }
-}
diff --git a/scripts/virtualization/test2.assembly.lp b/scripts/virtualization/test2.assembly.lp
deleted file mode 100644
index 8ce61dc..0000000
--- a/scripts/virtualization/test2.assembly.lp
+++ /dev/null
@@ -1,45 +0,0 @@
-% INPUT
-%-----------------------------------
-% assign_sizo(..).
-
-sizo(Sizo):-
- bind_scope(_, assign_sizo(Sizo), strong).
-
-dict_sizo(Sizo, Id):-
- Id= #sum{ 1, SizoLess : sizo(SizoLess), SizoLess < Sizo};
- sizo(Sizo).
-
-% connect to latex
-%-----------------------------------
-latex_registered_subjects(sizo, Sizo):- sizo(Sizo).
-
-latex_scope_demand(ScopeDemandSizo, sizo):-
- bind(Target, demand(sizo));
- Target = s(_, _, ScopeDemandSizo).
-
-bind_scope(Scope, Sizo, strong):-
- bind_scope(Scope, assign_sizo(Sizo), strong).
-
-% register late query
-%-----------------------------------
-late(Target, SymbolSizo, (SizoAny), sizo_current(SizoAny)):-
- bind(Target, demand(sizo));
- Target=s(_, _, TargetS);
- scope_fn(TargetS, Fn);
- latex_symbol(Fn, sizo, SymbolSizo);
- sizo(SizoAny).
-
-% polymorphism based on virtualizaion strategy
-%-----------------------------------
-dfa_callguard(SymbRet, strategy(Strategy)):-
- dfa_callfn(SymbRet, FnName);
- bind_func(FnName, requires(virt_dereference_strategy));
- virt_dereference_strategy(Strategy).
-
-
-% IMPLEMENTATION
-%=========================================================== .
-virt_dereference_strategy(prefix) :- 2 #count{Sizo: sizo(Sizo)}.
-virt_dereference_strategy(none) :- not virt_dereference_strategy(prefix).
-
-
diff --git a/scripts/virtualization/test2.xreate b/scripts/virtualization/test2.xreate
deleted file mode 100644
index 0051bd4..0000000
--- a/scripts/virtualization/test2.xreate
+++ /dev/null
@@ -1,57 +0,0 @@
-interface(extern-c){
- externalLibs = library:: pkgconfig("libxml-2.0").
-
- include {
- externalLibs = {"scripts/virtualization/test1.h"}
- }.
-}
-
-import raw ("scripts/virtualization/test2.assembly.lp").
-import raw ("scripts/cfa/context.lp").
-
-DictSizo = type slave dict_sizo.
-Sizo = type slave sizo.
-
-guard:: strategy(prefix)
-{
- virt_dereferenceFilename = function(filename:: string):: string; requires(virt_dereference_strategy)
- {
- dictSizo = intrinsic query("dict_sizo")::[DictSizo].
-
- sizoId = intrinsic query late("sizo_current"->sizoCurrent:: Sizo):: int; demand(sizo)
- {
- loop fold(dictSizo->entry::DictSizo, 0->id):: int
- {
- if(entry[0] == sizoCurrent):: int { entry[1] } else { id }
- }
- }.
-
- buf = "000000000"::string.
- seq
- { sprintf(buf, "%d/%s", sizoId, filename) }
- { buf }
- }
-}
-
-guard:: strategy(none)
-{
- virt_dereferenceFilename = function(filename:: string):: string; requires(virt_dereference_strategy)
- {
- filename
- }
-}
-
-virt_openFile = function(filename:: string):: int
-{
- filenameReal = virt_dereferenceFilename(filename):: string.
- seq{printf("file opened: %s ", filenameReal)}
-}
-
-main = function:: int; entry
-{
- seq
- { context::assign_sizo(domainA). virt_openFile("test1") }
- { context::assign_sizo(domainA). virt_openFile("test1") }
- { 0 }
-}
-
diff --git a/scripts/virtualization/test3.assembly.lp b/scripts/virtualization/test3.assembly.lp
deleted file mode 100644
index cb7af52..0000000
--- a/scripts/virtualization/test3.assembly.lp
+++ /dev/null
@@ -1,63 +0,0 @@
-% INPUT
-%-----------------------------------
-% assign_sizo(..).
-
-sizo(Sizo):-
- bind_scope(_, assign_sizo(Sizo), strong).
-
-dict_sizo(Sizo, Id):-
- Id= #sum{ 1, SizoLess : sizo(SizoLess), SizoLess < Sizo};
- sizo(Sizo).
-
-% connect to latex
-%-----------------------------------
-latex_registered_subjects(sizo, Sizo):- sizo(Sizo).
-
-latex_scope_demand(ScopeDemandSizo, sizo):-
- bind(Target, demand(sizo));
- Target = s(_, _, ScopeDemandSizo).
-
-bind_scope(Scope, Sizo, strong):-
- bind_scope(Scope, assign_sizo(Sizo), strong).
-
-% register late query
-%-----------------------------------
-late(Target, SymbolSizo, (SizoAny), sizo_current(SizoAny)):-
- bind(Target, demand(sizo));
- Target=s(_, _, TargetS);
- scope_fn(TargetS, Fn);
- latex_symbol(Fn, sizo, SymbolSizo);
- sizo(SizoAny).
-
-% polymorphism based on virtualizaion strategy
-%-----------------------------------
-late(SymbRet, SymbolSizo, Sizo, dfa_callguard(SymbRet, strategy(Strategy))):-
- dfa_callfn(SymbRet, FnName);
- bind_func(FnName, requires(virt_dereference_strategy));
- SymbRet=s(_, _, ScopeCaller);
- scope_fn(ScopeCaller, Fn);
- latex_symbol(Fn, sizo, SymbolSizo);
- sizo(Sizo);
- virt_dereference_strategy(Sizo, Strategy).
-
-
-% IMPLEMENTATION
-%=========================================================== .
-
-sizo_properties(Sizo, Prop):-
- bind_scope(Scope, define_sizo_prop(Prop), strong);
- bind_scope(Scope, Sizo, strong);
- sizo(Sizo).
-
-virt_dereference_strategy(SizoOther, prefix):-
- sizo_properties(Sizo, inner);
- SizoOther <> Sizo;
- sizo(SizoOther).
-
-virt_dereference_strategy(Sizo, prefix):-
- sizo_properties(Sizo, outer).
-
-virt_dereference_strategy(Sizo, none) :-
- not virt_dereference_strategy(Sizo, prefix);
- sizo(Sizo).
-
diff --git a/scripts/virtualization/test3.xreate b/scripts/virtualization/test3.xreate
deleted file mode 100644
index 468a25d..0000000
--- a/scripts/virtualization/test3.xreate
+++ /dev/null
@@ -1,57 +0,0 @@
-interface(extern-c){
- externalLibs = library:: pkgconfig("libxml-2.0").
-
- include {
- externalLibs = {"scripts/virtualization/test1.h"}
- }.
-}
-
-import raw ("scripts/virtualization/test3.assembly.lp").
-import raw ("scripts/cfa/context.lp").
-
-DictSizo = type slave dict_sizo.
-Sizo = type slave sizo.
-
-guard:: strategy(prefix)
-{
- virt_dereferenceFilename = function(filename:: string):: string; requires(virt_dereference_strategy)
- {
- dictSizo = intrinsic query("dict_sizo")::[DictSizo].
-
- sizoId = intrinsic query late("sizo_current"->sizoCurrent:: Sizo):: int; demand(sizo)
- {
- loop fold(dictSizo->entry::DictSizo, 0->id):: int
- {
- if(entry[0] == sizoCurrent):: int { entry[1] } else { id }
- }
- }.
-
- buf = "000000000"::string.
- seq
- { sprintf(buf, "%d/%s", sizoId, filename) }
- { buf }
- }
-}
-
-guard:: strategy(none)
-{
- virt_dereferenceFilename = function(filename:: string):: string; requires(virt_dereference_strategy)
- {
- filename
- }
-}
-
-virt_openFile = function(filename:: string):: int
-{
- filenameReal = virt_dereferenceFilename(filename):: string.
- printf("file opened: %s ", filenameReal)
-}
-
-main = function:: int; entry
-{
- seq
- { context::assign_sizo(domainA); define_sizo_prop(inner). virt_openFile("test1") }
- { context::assign_sizo(domainB); define_sizo_prop(outer). virt_openFile("test1") }
- { 0 }
-}
-
diff --git a/scripts/virtualization/virtualization.lp b/scripts/virtualization/virtualization.lp
new file mode 100644
index 0000000..2fa8f73
--- /dev/null
+++ b/scripts/virtualization/virtualization.lp
@@ -0,0 +1,63 @@
+virt_sizo(Sizo):-
+ bind_scope(_, assign_sizo(Sizo), strong).
+
+virt_resource(files).
+
+virt_sizo_control(Sizo, Resource):-
+ bind_scope(Scope, assign_sizo_control(Resource), strong);
+ bind_scope(Scope, assign_sizo(Sizo), strong).
+
+% Decisions
+%-----------------------------------
+virt_sizo_strategy(Sizo, Resource, direct):-
+ not virt_sizo_control(Sizo, Resource);
+ virt_resource(Resource);
+ virt_sizo(Sizo).
+
+activate_strategy_prefix(prefix) :-
+ 2 #count{Sizo: virt_sizo_control(Sizo, files)}.
+
+virt_sizo_strategy(Sizo, files, prefix):-
+ activate_strategy_prefix(prefix);
+ virt_sizo_control(Sizo, files);
+ not decided(virt_strategy(Sizo, files), 2).
+
+virt_sizo_strategy(Sizo, Resource, common):-
+ virt_sizo_control(Sizo, Resource);
+ not virt_sizo_strategy(Sizo, Resource, prefix);
+ not decided(virt_strategy(Sizo, files), 2).
+
+
+dict_sizo(Sizo, Id):-
+ Id= #sum{ 1, SizoLess : virt_sizo(SizoLess), SizoLess < Sizo};
+ virt_sizo(Sizo).
+
+% Connect to Latex
+%-----------------------------------
+latex_registered_subjects(sizo, Sizo):- virt_sizo(Sizo).
+
+latex_scope_demand(ScopeDemandSizo, sizo):-
+ bind(Target, demand(sizo));
+ Target = s(_, _, ScopeDemandSizo).
+
+bind_scope(Scope, Sizo, strong):-
+ bind_scope(Scope, assign_sizo(Sizo), strong).
+
+% Polymorphism based on virtualizaion strategy
+%-----------------------------------
+dfa_callguard(SymbRet, strategy(Strategy)):-
+ dfa_callfn(SymbRet, Fn);
+ bind_func(Fn, assign_zek_access(Resource));
+ SymbRet = s(_, _, Scope);
+ bind_scope(Scope, assign_sizo(Sizo), strong);
+ virt_sizo_strategy(Sizo, Resource, Strategy).
+
+late(SymbRet, SymbolSizo, Sizo, dfa_callguard(SymbRet, strategy(Strategy))):-
+ bind_func(FnName, assign_zek_access(Resource));
+ virt_sizo_strategy(Sizo, Resource, Strategy);
+
+ dfa_callfn(SymbRet, FnName);
+ SymbRet=s(_, _, ScopeCaller);
+ scope_fnbody(ScopeCaller, FnCallerBody);
+ latex_symbol(FnCallerBody, sizo, SymbolSizo);
+ virt_sizo(Sizo).

Event Timeline