No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:37 AM
diff --git a/coco/gen-grammar b/coco/gen-grammar
deleted file mode 100755
index ed6c115..0000000
--- a/coco/gen-grammar
+++ /dev/null
@@ -1,6 +0,0 @@
-COCO_EXECUTABLE=${1:-cococpp}
-COCO_FRAMES_PATH=${2:-/usr/share/coco-cpp/}
-
-echo "Run coco generator: "
-$COCO_EXECUTABLE ./xreate.ATG -frames $COCO_FRAMES_PATH
-
diff --git a/config/default.json b/config/default.json
index 807e420..33f43d3 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,69 +1,70 @@
{
"containers": {
"id": {
"implementations": "impl_fulfill_cluster",
"clusters": "var_cluster",
"prototypes": "proto_cluster",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
"onthefly": "on_the_fly"
}
},
"logging": {
"id": "logging"
},
"function-entry": "entry",
"clasp": {
"bindings" : {
"variable": "bind",
"function": "bind_func",
"scope": "bind_scope",
"function_demand" : "bind_function_demand",
"scope_decision": "bind_scope_decision"
},
"context" : {
"decisions":{
"dependent": "resolution_dependency"
},
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
"template": "default",
"templates": {
"default": "*-",
"adhocs": "Adhoc.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"ast": "AST.*",
"cfa": "CFA.*",
"dfa": "DFA.*",
"compilation": "Compilation.functionEntry1*",
"diagnostic": "Diagnostic.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"types": "Types.*-",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2*",
"dsl": "Interpretation.*:InterpretationExamples.*",
"context": "Context.*",
"containers": "Containers.*",
- "loops": "Loop.*"
+ "loops": "Loop.*",
+ "modules": "Modules.*"
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 78a19cc..2f998dd 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,219 +1,228 @@
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("LLVM DEFS: " ${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option)
message("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}/../coco/)
-set(COCO_SOURCE_FILES
- ${COCO_GRAMMAR_PATH}/Parser.cpp
- ${COCO_GRAMMAR_PATH}/Scanner.cpp)
+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}
- COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar ${COCO_EXECUTABLE} ${COCO_FRAMES_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
+ 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
+ modules.cpp
+ ast.cpp
+ xreatemanager.cpp
+ misc/xreatemanager-decorators.cpp
compilation/pointerarithmetic.cpp
compilation/transformations.cpp
compilation/transformersaturation.cpp
pass/compilepass.cpp
pass/dfapass.cpp
analysis/dfagraph.cpp
-
pass/versionspass.cpp
compilation/targetinterpretation.cpp
-
attachments.cpp
- ast.cpp
-
- ExternLayer.cpp
-
- analysis/cfagraph.cpp
-
- analysis/aux.cpp
- compilation/containers.cpp
- compilation/advanced.cpp
-
- clasplayer.cpp
- compilation/latecontextcompiler2.cpp
- query/context.cpp
-
- llvmlayer.cpp
- utils.cpp
- passmanager-bare.cpp
- passmanager-full.cpp
- pass/abstractpass.cpp
-
- pass/cfapass.cpp
- pass/adhocpass.cpp
- contextrule.cpp
- query/containers.cpp
- pass/interpretationpass.cpp
- analysis/DominatorsTreeAnalysisProvider.cpp
- serialization/expressionserializer.cpp
+ ExternLayer.cpp
+ analysis/cfagraph.cpp
+ analysis/aux.cpp
+ compilation/containers.cpp
+ compilation/advanced.cpp
+ clasplayer.cpp
+ compilation/latecontextcompiler2.cpp
+ query/context.cpp
+ llvmlayer.cpp
+ utils.cpp
+ pass/abstractpass.cpp
+ pass/cfapass.cpp
+ pass/adhocpass.cpp
+ contextrule.cpp
+ query/containers.cpp
+ pass/interpretationpass.cpp
+ analysis/DominatorsTreeAnalysisProvider.cpp
+ misc/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 ${SOURCE_FILES} ${COCO_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
+ 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/ast.cpp b/cpp/src/ast.cpp
index 6a6cccf..f50b3d3 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,915 +1,925 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
namespace std{
std::size_t
hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const
{return s.id ^ (s.version << 2);}
bool
equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const
{ return __x.id == __y.id && __x.version == __y.version; }
}
using namespace std;
namespace xreate {
Atom<Identifier_t>::Atom(const std::wstring& value) {
__value = wstring_to_utf8(value);
}
Atom<Identifier_t>::Atom(std::string && name) : __value(name)
{}
const std::string&
Atom<Identifier_t>::get() const {
return __value;
}
Atom<Number_t>::Atom(wchar_t* value) {
//DEBT reconsider number literal recognition
__value = wcstol(value, 0, 10);
}
Atom<Number_t>::Atom(int value)
: __value(value) {
}
double
Atom<Number_t>::get()const {
return __value;
}
Atom<String_t>::Atom(const std::wstring& value) {
assert(value.size() >=2);
__value = wstring_to_utf8(value.substr(1, value.size() -2));
}
const std::string&
Atom<String_t>::get() const {
return __value;
}
class ExpressionHints {
public:
static bool
isStringValueValid(const Expression& e) {
switch (e.__state) {
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
return true;
case Expression::NUMBER:
case Expression::BINDING:
case Expression::VARIANT:
return false;
case Expression::COMPOUND:
{
switch (e.op) {
case Operator::CALL:
return true;
default: return false;
}
}
}
return false;
}
static bool
isDoubleValueValid(const Expression& e) {
switch (e.__state) {
case Expression::NUMBER:
case Expression::VARIANT:
return true;
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
case Expression::COMPOUND:
case Expression::BINDING:
return false;
}
return false;
}
};
class TypesResolver {
private:
const AST* ast;
std::map<std::string, TypeAnnotation> scope;
std::map<TypeAnnotation, int> signatures;
ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
return TypesResolver(ast, scope, signatures)(t, args);
}
std::vector<TypeAnnotation>
expandOperands(const std::vector<TypeAnnotation>& operands) {
std::vector<TypeAnnotation> pack;
pack.reserve(operands.size());
std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation & t) {
return expandType(t);
});
return pack;
}
public:
TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
: ast(root), scope(scopeOuter), signatures(signaturesOuter) {
}
ExpandedType
operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
//assert(args.size() == t.bindings.size()); // invalid number of arguments
for (size_t i = 0; i < args.size(); ++i) {
scope[t.bindings.at(i)] = args.at(i);
}
switch (t.__operator) {
case TypeOperator::ARRAY:
{
assert(t.__operands.size() == 1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
}
case TypeOperator::STRUCT:
{
assert(t.__operands.size());
std::vector<TypeAnnotation>&& pack = expandOperands(t.__operands);
auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack));
tnew.fields = t.fields;
return ExpandedType(move(tnew));
};
case TypeOperator::CALL:
{
std::string alias = t.__valueCustom;
//find in local scope:
TypeAnnotation ty;
if (scope.count(alias)) {
ty = scope.at(alias);
} else if (ast->__indexTypeAliases.count(alias)) {
ty = ast->__indexTypeAliases.at(alias);
} else {
assert(false && "Undefined or external type");
}
std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
TypeAnnotation signature(TypeOperator::CALL, move(operands));
signature.__valueCustom = alias;
if (signatures.count(signature)) {
auto link = TypeAnnotation(TypeOperator::LINK,{});
link.conjuctionId = signatures.at(signature);
return ExpandedType(move(link));
}
int cid = signatures.size();
signatures[signature] = cid;
TypeAnnotation tyResult = expandType(ty, operands);
tyResult.conjuctionId = cid;
return ExpandedType(move(tyResult));
};
case TypeOperator::CUSTOM:
{
std::string alias = t.__valueCustom;
/*
if (signatures.count(alias)) {
return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
}
signatures[alias].emplace(t);
*/
//find in local scope:
if (scope.count(alias)) {
return expandType(scope.at(alias));
}
// find in general scope:
if (ast->__indexTypeAliases.count(alias)) {
return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
}
//if type is unknown keep it as is.
return ExpandedType(TypeAnnotation(t));
};
case TypeOperator::ACCESS:
{
std::string alias = t.__valueCustom;
ExpandedType tyAlias = ExpandedType(TypeAnnotation());
//find in local scope:
if (scope.count(alias)) {
tyAlias = expandType(scope.at(alias));
//find in global scope:
} else if ((ast->__indexTypeAliases.count(alias))) {
tyAlias = expandType(ast->__indexTypeAliases.at(alias));
} else {
assert(false && "Undefined or external type");
}
assert(tyAlias->__operator == TypeOperator::STRUCT);
for (const string& field : t.fields) {
auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
assert(fieldIt != tyAlias->fields.end() && "unknown field");
int fieldId = fieldIt - tyAlias->fields.begin();
tyAlias = expandType(tyAlias->__operands.at(fieldId));
}
return tyAlias;
}
case TypeOperator::TUPLE:
{
assert(t.__operands.size());
std::vector<TypeAnnotation> pack;
pack.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation & t) {
return expandType(t);
});
return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
}
case TypeOperator::VARIANT:
{
return ExpandedType(TypeAnnotation(t));
}
case TypeOperator::NONE:
{
return ExpandedType(TypeAnnotation(t));
}
default:
assert(false);
}
assert(false);
return ExpandedType(TypeAnnotation());
}
};
TypeAnnotation::TypeAnnotation()
: __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid)
{}
TypeAnnotation::TypeAnnotation(TypePrimitive typ)
: __value(typ) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
: TypeAnnotation(TypeOperator::ARRAY,{typ}) {
__size = size;
}
bool
TypeAnnotation::isValid() const{
return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
}
bool
TypeAnnotation::operator<(const TypeAnnotation& t) const {
if (__operator != t.__operator) return __operator < t.__operator;
if (__operator == TypeOperator::NONE)
return __value < t.__value;
if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
if (__valueCustom != t.__valueCustom)
return __valueCustom < t.__valueCustom;
}
return __operands < t.__operands;
}
/*
TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
{}
*/
void
TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
bindings.reserve(bindings.size() + params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
void
TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
fields.reserve(fields.size() + listFields.size());
std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
unsigned int Expression::nextVacantId = 0;
Expression::Expression(const Atom<Number_t>& number)
: Expression() {
__state=NUMBER; op=Operator::NONE; __valueD=number.get();
}
Expression::Expression(const Atom<String_t>& a)
: Expression(){
__state=STRING; op=Operator::NONE; __valueS=a.get();
}
Expression::Expression(const Atom<Identifier_t> &ident)
: Expression() {
__state=IDENT; op=Operator::NONE; __valueS=ident.get();
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: Expression() {
__state=COMPOUND; op=oprt;
if (op == Operator::CALL) {
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
operands.insert(operands.end(), params.begin() + 1, params.end());
return;
}
operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt) {
op = oprt;
switch (op) {
case Operator::NONE:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg) {
operands.push_back(arg);
}
void
Expression::addTags(const std::list<Expression> tags) const{
std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
[](const Expression& tag){
return make_pair(tag.getValueString(), tag);
});
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
addBindings(params.begin(), params.end());
}
void
Expression::bindType(TypeAnnotation t) {
type = move(t);
}
void
Expression::addBlock(ManagedScpPtr scope) {
blocks.push_back(scope.operator->());
}
const std::vector<Expression>&
Expression::getOperands() const {
return operands;
}
double
Expression::getValueDouble() const {
return __valueD;
}
const std::string&
Expression::getValueString() const {
return __valueS;
}
void
Expression::setValue(const Atom<Identifier_t>&& v) {
__valueS = v.get();
}
void Expression::setValueDouble(double value) {
__valueD = value;
}
bool
Expression::isValid() const {
return (__state != INVALID);
}
bool
Expression::isDefined() const {
return (__state != BINDING);
}
Expression::Expression()
: __state(INVALID), op(Operator::NONE), id(nextVacantId++)
{ }
- AST::AST() {
- Attachments::init<VariableVersion>();
- Attachments::init<Symbol>();
- }
+namespace details { namespace incomplete {
+AST::AST() {
+ Attachments::init<VariableVersion>();
+ Attachments::init<Symbol>();
+}
- void
- AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
- __interfacesData.emplace(interface, move(data));
- }
+void
+AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
+ __interfacesData.emplace(interface, move(data));
+}
- void
- AST::addDFAData(Expression &&data) {
- __dfadata.push_back(data);
- }
+void
+AST::addDFAData(Expression &&data) {
+ __dfadata.push_back(data);
+}
- void
- AST::addExternData(ExternData &&data) {
- __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
- }
+void
+AST::addExternData(ExternData &&data) {
+ __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
+}
- void
- AST::add(Function* f) {
- __functions.push_back(f);
- __indexFunctions.emplace(f->getName(), __functions.size() - 1);
- }
+void
+AST::add(Function* f) {
+ __functions.push_back(f);
+ __indexFunctions.emplace(f->getName(), __functions.size() - 1);
+}
- void
- AST::add(MetaRuleAbstract *r) {
- __rules.push_back(r);
- }
+void
+AST::add(MetaRuleAbstract *r) {
+ __rules.push_back(r);
+}
- void
- AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
- if (t.__operator == TypeOperator::VARIANT) {
- for (int i = 0, size = t.fields.size(); i < size; ++i) {
- __dictVariants.emplace(t.fields[i], make_pair(t, i));
- }
+void
+AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
+ if (t.__operator == TypeOperator::VARIANT) {
+ for (int i = 0, size = t.fields.size(); i < size; ++i) {
+ __dictVariants.emplace(t.fields[i], make_pair(t, i));
}
-
- __indexTypeAliases.emplace(alias.get(), move(t));
}
- ManagedScpPtr
- AST::add(CodeScope* scope) {
- this->__scopes.push_back(scope);
- return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
- }
+ __indexTypeAliases.emplace(alias.get(), move(t));
+}
+
+ManagedScpPtr
+AST::add(CodeScope* scope) {
+ this->__scopes.push_back(scope);
+ return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
+}
- std::string
- AST::getModuleName() {
- const std::string name = "moduleTest";
+std::string
+AST::getModuleName() {
+ const std::string name = "moduleTest";
- return name;
+ return name;
+}
+
+ManagedPtr<Function>
+AST::findFunction(const std::string& name) {
+ int count = __indexFunctions.count(name);
+ if (!count) {
+ return ManagedFnPtr::Invalid();
}
- ManagedPtr<Function>
- AST::findFunction(const std::string& name) {
- int count = __indexFunctions.count(name);
- if (!count) {
- return ManagedFnPtr::Invalid();
- }
+ assert(count == 1);
- assert(count == 1);
+ auto range = __indexFunctions.equal_range(name);
+ return ManagedPtr<Function>(range.first->second, &this->__functions);
+}
- auto range = __indexFunctions.equal_range(name);
- return ManagedPtr<Function>(range.first->second, &this->__functions);
+std::list<ManagedFnPtr>
+AST::getAllFunctions() const {
+ const size_t size = __functions.size();
+
+ std::list<ManagedFnPtr> result;
+ for (size_t i = 0; i < size; ++i) {
+ result.push_back(ManagedFnPtr(i, &this->__functions));
}
- std::list<ManagedFnPtr>
- AST::getAllFunctions() const {
- const size_t size = __functions.size();
+ return result;
+}
- std::list<ManagedFnPtr> result;
- for (size_t i = 0; i < size; ++i) {
- result.push_back(ManagedFnPtr(i, &this->__functions));
- }
+//TASK select default specializations
- return result;
- }
+std::list<ManagedFnPtr>
+AST::getFunctionVariants(const std::string& name) const {
+ auto functions = __indexFunctions.equal_range(name);
- //TASK select default specializations
+ std::list<ManagedFnPtr> result;
+ std::transform(functions.first, functions.second, inserter(result, result.end()),
+ [this](auto f) {
+ return ManagedFnPtr(f.second, &this->__functions);
+ });
- std::list<ManagedFnPtr>
- AST::getFunctionVariants(const std::string& name) const {
- auto functions = __indexFunctions.equal_range(name);
+ return result;
+}
- std::list<ManagedFnPtr> result;
- std::transform(functions.first, functions.second, inserter(result, result.end()),
- [this](auto f) {
- return ManagedFnPtr(f.second, &this->__functions);
- });
+template<>
+ManagedPtr<Function>
+AST::begin<Function>() {
+ return ManagedPtr<Function>(0, &this->__functions);
+}
- return result;
- }
+template<>
+ManagedPtr<CodeScope>
+AST::begin<CodeScope>() {
+ return ManagedPtr<CodeScope>(0, &this->__scopes);
+}
- template<>
- ManagedPtr<Function>
- AST::begin<Function>() {
- return ManagedPtr<Function>(0, &this->__functions);
- }
+template<>
+ManagedPtr<MetaRuleAbstract>
+AST::begin<MetaRuleAbstract>() {
+ return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
+}
- template<>
- ManagedPtr<CodeScope>
- AST::begin<CodeScope>() {
- return ManagedPtr<CodeScope>(0, &this->__scopes);
- }
+bool
+AST::recognizeVariantIdentifier(Expression& identifier) {
+ assert(identifier.__state == Expression::IDENT);
- template<>
- ManagedPtr<MetaRuleAbstract>
- AST::begin<MetaRuleAbstract>() {
- return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
+ std::string variant = identifier.getValueString();
+ if (!__dictVariants.count(variant)) {
+ return false;
}
- Expanded<TypeAnnotation>
- AST::expandType(const TypeAnnotation &t) const {
- return TypesResolver(this)(t);
- }
+ auto record = __dictVariants.at(variant);
+ const TypeAnnotation& typ = record.first;
- Expanded<TypeAnnotation>
- AST::findType(const std::string& name) {
- // find in general scope:
- if (__indexTypeAliases.count(name))
- return expandType(__indexTypeAliases.at(name));
+ identifier.__state = Expression::VARIANT;
+ identifier.setValueDouble(record.second);
+ identifier.type = typ;
- //if type is unknown keep it as is.
- TypeAnnotation t(TypeOperator::CUSTOM,{});
- t.__valueCustom = name;
- return ExpandedType(move(t));
- }
+ return true;
+}
- bool
- AST::recognizeVariantIdentifier(Expression& identifier) {
- assert(identifier.__state == Expression::IDENT);
+void
+AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
+ bucketUnrecognizedIdentifiers.emplace(scope, id);
+}
- std::string variant = identifier.getValueString();
- if (!__dictVariants.count(variant)) {
- return false;
+void
+AST::recognizePostponedIdentifiers() {
+ for(const auto& identifier: bucketUnrecognizedIdentifiers){
+ if (!identifier.first->recognizeIdentifier(identifier.second)){
+ //exception: Ident not found
+ std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl;
+ assert(false && "Symbol not found");
}
+ }
+}
- auto record = __dictVariants.at(variant);
- const TypeAnnotation& typ = record.first;
+xreate::AST*
+AST::finalize() {
+ //all finalization steps:
+ recognizePostponedIdentifiers();
- identifier.__state = Expression::VARIANT;
- identifier.setValueDouble(record.second);
- identifier.type = typ;
+ return reinterpret_cast<xreate::AST*>(this);
+}
+}} //namespace details::incomplete
+
+Expanded<TypeAnnotation>
+AST::findType(const std::string& name) {
+ // find in general scope:
+ if (__indexTypeAliases.count(name))
+ return expandType(__indexTypeAliases.at(name));
+
+ //if type is unknown keep it as is.
+ TypeAnnotation t(TypeOperator::CUSTOM,{});
+ t.__valueCustom = name;
+ return ExpandedType(move(t));
+}
- return true;
- }
+Expanded<TypeAnnotation>
+AST::expandType(const TypeAnnotation &t) const {
+ return TypesResolver(this)(t);
+}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0)) {
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod) {
string name = tag.getValueString();
__tags.emplace(move(name), move(tag));
}
const std::map<std::string, Expression>&
Function::getTags() const {
return __tags;
}
CodeScope*
Function::getEntryScope() const {
return __entry;
}
void
Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument) {
__entry->addBinding(move(name), move(argument));
}
const std::string&
Function::getName() const {
return __name;
}
ScopedSymbol
CodeScope::registerIdentifier(const Expression& identifier) {
VariableVersion version = Attachments::get<VariableVersion>(identifier, VERSION_NONE);
auto result = __identifiers.emplace(identifier.getValueString(), __vCounter);
if (result.second){
++__vCounter;
return {__vCounter-1, version};
}
return {result.first->second, version};
}
bool
CodeScope::recognizeIdentifier(const Expression& identifier) const{
VariableVersion version = Attachments::get<VariableVersion>(identifier, VERSION_NONE);
const std::string& name = identifier.getValueString();
//search identifier in the current block
if (__identifiers.count(name)){
VNameId id = __identifiers.at(name);
Symbol s;
s.identifier = ScopedSymbol{id, version};
s.scope = const_cast<CodeScope*>(this);
Attachments::put<Symbol>(identifier, s);
return true;
}
//search in the parent scope
if (__parent)
{
return __parent->recognizeIdentifier(identifier);
}
return false;
}
ScopedSymbol
CodeScope::getSymbol(const std::string& alias){
assert(__identifiers.count(alias));
VNameId id = __identifiers.at(alias);
return {id, VERSION_NONE};
}
- void
- AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
- binUnrecognizedIdentifiers.emplace(scope, id);
- }
-
- void
- AST::recognizePostponedIdentifiers() {
- for(const auto& identifier: binUnrecognizedIdentifiers){
- if (!identifier.first->recognizeIdentifier(identifier.second)){
- //exception: Ident not found
- std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl;
- assert(false && "Symbol not found");
- }
- }
- }
-
void
CodeScope::addBinding(Expression&& var, Expression&& argument) {
argument.__state = Expression::BINDING;
__bindings.push_back(var.getValueString());
ScopedSymbol binding = registerIdentifier(var);
__declarations[binding] = move(argument);
}
void
CodeScope::addDeclaration(Expression&& var, Expression&& body) {
ScopedSymbol s = registerIdentifier(var);
__declarations[s] = move(body);
}
CodeScope::CodeScope(CodeScope* parent)
: __parent(parent) {
}
CodeScope::~CodeScope() {
}
void
CodeScope::setBody(const Expression &body) {
__declarations[ScopedSymbol::RetSymbol] = body;
}
Expression&
CodeScope::getBody() {
return __declarations[ScopedSymbol::RetSymbol];
}
const Expression&
CodeScope::getDeclaration(const Symbol& symbol) {
CodeScope* self = symbol.scope;
return self->getDeclaration(symbol.identifier);
}
const Expression&
CodeScope::getDeclaration(const ScopedSymbol& symbol){
assert(__declarations.count(symbol) && "Symbol's declaration not found");
return __declarations.at(symbol);
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e) {
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards)) {
}
MetaRuleAbstract::~MetaRuleAbstract() {
}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
}
RuleWarning::~RuleWarning() {
}
void
RuleWarning::compile(ClaspLayer& layer) {
//TODO restore addRuleWarning
//layer.addRuleWarning(*this);
}
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id < s2.id) || (s1.id==s2.id && s1.version < s2.version);
}
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id == s2.id) && (s1.version == s2.version);
}
bool operator<(const Symbol& s1, const Symbol& s2) {
return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
bool operator==(const Symbol& s1, const Symbol& s2) {
return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
}
bool operator<(const Expression&a, const Expression&b) {
if (a.__state != b.__state) return a.__state < b.__state;
assert(a.__state != Expression::INVALID);
switch (a.__state) {
case Expression::IDENT:
case Expression::STRING:
case Expression::VARIANT:
return a.getValueString() < b.getValueString();
case Expression::NUMBER:
return a.getValueDouble() < b.getValueDouble();
case Expression::COMPOUND:
{
assert(a.blocks.size() == 0);
assert(b.blocks.size() == 0);
if (a.op != b.op){
return a.op < b.op;
}
bool flagAValid = ExpressionHints::isStringValueValid(a);
bool flagBValid = ExpressionHints::isStringValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid){
if (a.getValueString() != b.getValueString()) {
return a.getValueString() < b.getValueString();
}
}
flagAValid = ExpressionHints::isDoubleValueValid(a);
flagBValid = ExpressionHints::isDoubleValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid){
if (a.getValueDouble() != b.getValueDouble()) {
return a.getValueDouble() < b.getValueDouble();
}
}
if (a.operands.size() != b.operands.size()) {
return (a.operands.size() < b.operands.size());
}
for (size_t i = 0; i < a.operands.size(); ++i) {
bool result = a.operands[i] < b.operands[i];
if (result) return true;
}
return false;
}
case Expression::BINDING:
case Expression::INVALID:
assert(false);
}
return false;
}
bool
Expression::operator==(const Expression& other) const {
if (this->__state != other.__state) return false;
if (ExpressionHints::isStringValueValid(*this)) {
if (this->__valueS != other.__valueS) return false;
}
if (ExpressionHints::isDoubleValueValid(*this)) {
if (this->__valueD != other.__valueD) return false;
}
if (this->__state != Expression::COMPOUND) {
return true;
}
if (this->op != other.op) {
return false;
}
if (this->operands.size() != other.operands.size()) {
return false;
}
for (size_t i = 0; i<this->operands.size(); ++i) {
if (!(this->operands[i] == other.operands[i])) return false;
}
assert(!this->blocks.size());
assert(!other.blocks.size());
return true;
}
const ScopedSymbol
ScopedSymbol::RetSymbol = ScopedSymbol{0, VERSION_NONE};
}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 8c24e48..87dbecc 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,556 +1,562 @@
#ifndef AST_H
#define AST_H
#include "attachments.h"
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "utils.h"
#include <algorithm>
namespace llvm {
class Value;
}
namespace xreate {
struct String_t {
};
struct Identifier_t {
};
struct Number_t {
};
struct Type_t {
};
template<typename A>
class Atom {
};
//DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
template<> class
Atom<Identifier_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
template<>
class Atom<Number_t> {
public:
Atom(wchar_t* value);
Atom(int value);
double get()const;
private:
double __value;
};
template<>
class Atom<String_t> {
public:
Atom(const std::wstring& value);
const std::string& get() const;
private:
std::string __value;
};
enum class TypePrimitive {
Invalid, Bool, I8, I32, I64, Num, Int, Float, String
};
enum class TypeOperator {
NONE, CALL, CUSTOM, VARIANT, ARRAY, TUPLE, STRUCT, ACCESS, LINK
};
struct llvm_array_tag {
};
struct struct_tag {
};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
class TypeAnnotation {
public:
TypeAnnotation();
TypeAnnotation(const Atom<Type_t>& typ);
TypeAnnotation(TypePrimitive typ);
TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator<(const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
bool isValid() const;
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId = -1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator {
ADD, SUB, MUL, DIV,
EQU, NE, NEG, LSS,
LSE, GTR, GTE, LIST,
LIST_RANGE, LIST_NAMED,
CALL, CALL_INTRINSIC, NONE,
IMPL/* implication */, MAP,
FOLD, FOLD_INF, LOOP_CONTEXT,
INDEX, IF, SWITCH, SWITCH_ADHOC,
CASE, CASE_DEFAULT, LOGIC_AND,
ADHOC, CONTEXT_RULE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
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;
}
private:
unsigned int __id = 0;
const std::vector<Target*> * __storage = 0;
};
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
//To update ExpressionHints in case of any changes
struct Expression {
friend class CodeScope;
friend class ClaspLayer;
friend class CFAPass;
friend class ExpressionHints;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addTags(const std::list<Expression> tags) const;
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isValid() const;
bool isDefined() const;
bool operator==(const Expression& other) const;
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT, BINDING
} __state = INVALID;
Operator op;
unsigned int id;
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
TypeAnnotation type;
mutable std::map<std::string, Expression> tags;
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
static unsigned int nextVacantId;
};
bool operator< (const Expression&, const Expression&);
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom) {
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier {
NONE, ASSERT, REQUIRE
};
enum class DomainAnnotation {
FUNCTION, VARIABLE
};
class RuleArguments : public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards : public std::vector<Expression> {
public:
void add(Expression&& e);
};
class ClaspLayer;
class LLVMLayer;
class MetaRuleAbstract {
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(ClaspLayer& layer) = 0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning : public MetaRuleAbstract {
friend class ClaspLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(ClaspLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VNameId;
typedef int VariableVersion;
const VariableVersion VERSION_NONE = -2;
const VariableVersion VERSION_INIT = 0;
template<>
struct AttachmentsDict<VariableVersion>
{
typedef VariableVersion Data;
static const unsigned int key = 6;
};
struct ScopedSymbol{
VNameId id;
VariableVersion version;
static const ScopedSymbol RetSymbol;
};
struct Symbol {
ScopedSymbol identifier;
CodeScope * scope;
};
template<>
struct AttachmentsDict<Symbol>
{
typedef Symbol Data;
static const unsigned int key = 7;
};
}
namespace std
{
template<>
struct hash<xreate::ScopedSymbol>{
std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
template<>
struct equal_to<xreate::ScopedSymbol>{
bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
};
}
namespace xreate {
typedef std::pair<Expression, TagModifier> Tag;
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
class CodeScope {
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent = 0);
void setBody(const Expression& body);
Expression& getBody();
void addDeclaration(Expression&& var, Expression&& body);
void addBinding(Expression&& var, Expression&& argument);
static const Expression& getDeclaration(const Symbol& symbol);
const Expression& getDeclaration(const ScopedSymbol& symbol);
~CodeScope();
std::vector<std::string> __bindings;
std::map<std::string, VNameId> __identifiers;
CodeScope* __parent;
//TODO move __definitions to SymbolsAttachments data
//NOTE: definition of return type has zero(0) variable index
std::unordered_map<ScopedSymbol, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
VNameId __vCounter = 1;
ScopedSymbol registerIdentifier(const Expression& identifier);
public:
bool recognizeIdentifier(const Expression& identifier) const;
ScopedSymbol getSymbol(const std::string& alias);
};
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
void addTag(Expression&& tag, const TagModifier mod);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
Expression guardContext;
private:
std::map<std::string, Expression> __tags;
};
class ExternData;
struct ExternEntry {
std::string package;
std::vector<std::string> headers;
};
typedef Expanded<TypeAnnotation> ExpandedType;
enum ASTInterface {
CFA, DFA, Extern, Adhoc
};
struct FunctionSpecialization {
std::string guard;
size_t id;
};
struct FunctionSpecializationQuery {
std::unordered_set<std::string> context;
};
template<>
struct AttachmentsId<Expression>{
static unsigned int getId(const Expression& expression){
return expression.id;
}
};
template<>
struct AttachmentsId<Symbol>{
static unsigned int getId(const Symbol& s){
return s.scope->__declarations.at(s.identifier).id;
}
};
template<>
struct AttachmentsId<ManagedFnPtr>{
static unsigned int getId(const ManagedFnPtr& f){
const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
return AttachmentsId<Symbol>::getId(symbolFunction);
}
};
+namespace details { namespace incomplete {
class AST {
public:
AST();
//TASK extern and DFA interfaces move into addInterfaceData
/**
* DFA Interface
*/
void addDFAData(Expression&& data);
/**
* Extern Interface
*/
void addExternData(ExternData&& data);
void addInterfaceData(const ASTInterface& interface, Expression&& data);
void add(Function* f);
void add(MetaRuleAbstract* r);
ManagedScpPtr add(CodeScope* scope);
std::string getModuleName();
ManagedPtr<Function> findFunction(const std::string& name);
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
std::list<ManagedFnPtr> getAllFunctions() const;
std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
template<class Target>
ManagedPtr<Target> begin();
std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
FUNCTIONS_REGISTRY __indexFunctions;
// ***** TYPES SECTION *****
public:
std::map<std::string, TypeAnnotation> __indexTypeAliases;
- ExpandedType expandType(const TypeAnnotation &t) const;
- ExpandedType findType(const std::string& name);
+
void add(TypeAnnotation t, Atom<Identifier_t> alias);
-
+
+ // ***** SYMBOL RECOGNITION *****
//TODO revisit enums/variants, move to codescope
bool recognizeVariantIdentifier(Expression& identifier);
-
private:
std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
- ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
- const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
-
- // ***** SYMBOL RECOGNITION *****
+
public:
- std::set<std::pair<CodeScope*, Expression>> binUnrecognizedIdentifiers;
+ std::set<std::pair<CodeScope*, Expression>> bucketUnrecognizedIdentifiers;
public:
void postponeIdentifier(CodeScope* scope, const Expression& id);
void recognizePostponedIdentifiers();
+ xreate::AST* finalize();
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
+} } // namespace details::incomplete
+
+class AST: public details::incomplete::AST{
+public:
+ AST(): details::incomplete::AST() {}
+ ExpandedType expandType(const TypeAnnotation &t) const;
+ ExpandedType findType(const std::string& name);
+};
}
#endif // AST_H
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index 1fd3e48..5964ebe 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,158 +1,163 @@
//
// Created by pgess on 3/15/15.
//
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <type_traits>
namespace xreate
{
//Attachments dictionary
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
// static const unsigned int key (current unreserved - 9);
};
template<class Object>
struct AttachmentsId{
//static unsigned int getId(const Object& object);
};
template<class Data>
class IAttachmentsContainer{
protected:
virtual bool __exists(const unsigned int object)=0;
virtual Data& __get(const unsigned int object)=0;
virtual void __put(const unsigned int object, Data data)=0;
public:
template<class Id>
bool exists(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __exists(id);
}
template<class Id>
Data& get(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __get(id);
}
template<class Id>
Data get(const Id& object, const Data& dataDefault){
unsigned int id = AttachmentsId<Id>::getId(object);
if (! __exists(id)){
return dataDefault;
}
return __get(id);
}
template<class Id>
void put(const Id& object, Data data){
unsigned int id = AttachmentsId<Id>::getId(object);
__put(id, data);
}
virtual ~IAttachmentsContainer(){};
};
template<class Data>
class AttachmentsContainerDefault: public IAttachmentsContainer<Data>{
private:
std::unordered_map<unsigned int, Data> __data;
virtual bool __exists(const unsigned int id){
return __data.count(id);
}
virtual Data& __get(const unsigned int id){
return __data.at(id);
}
virtual void __put(const unsigned int id, Data data){
auto result = __data.emplace(id, data);
assert(result.second);
}
+
+public:
+ std::unordered_map<unsigned int, Data>& getRawStorage() {
+ return __data;
+ }
};
class Attachments{
private:
static std::vector<void*> __storage;
template<class Tag>
using Data = typename AttachmentsDict<Tag>::Data;
public:
template<class Tag, class Id>
static bool exists(const Id& object) {
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->exists<Id>(object);
}
template<class Tag, class Id>
static Data<Tag>& get(const Id& object){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get<Id>(object);
}
template<class Tag, class Id>
static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get<Id>(object, dataDefault);
}
template<class Tag, class Id>
static void put(const Id& object, Data<Tag> data){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
self->put<Id>(object, data);
}
template<class Tag>
static void init(){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
}
template<class Tag>
static void init(IAttachmentsContainer<Data<Tag>>* container){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = container;
}
};
}
#endif //_XREATE_ATTACHMENTS_H_
\ No newline at end of file
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index 65ff3fb..4073851 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,275 +1,275 @@
#include "clasplayer.h"
#include <iostream>
#include "utils.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <gringo/scripts.hh>
#include "analysis/aux.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "analysis/cfagraph.h"
#include "analysis/dfagraph.h"
using namespace std;
-//TODO escape identifiers started from upper case symbol
+//TODO escape identifiers started with upper case symbol
namespace xreate {
void
ClaspLayer::printWarnings(std::ostream& out)
{
const std::string warningTag = "warning";
auto warningsRange = __model.equal_range(warningTag);
for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) {
unsigned int warningId;
Gringo::Symbol params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning->second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
ClaspLayer::handleSolution(Gringo::Model const &model) {
std::list<std::string> warnings;
cout << "Model: " << endl;
const string& atomBindVar = Config::get("clasp.bindings.variable");
const string& atomBindFunc = Config::get("clasp.bindings.function");
const string& atomBindScope = Config::get("clasp.bindings.scope");
for (Gringo::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 name = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.emplace(move(name), move(atom));
}
__model.emplace(atomName, move(atom));
}
return true;
}
void
ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) {
dataCFA.reset(graph);
}
void
ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){
dataDFA.reset(graph);
}
void
ClaspLayer::addRuleWarning(const RuleWarning &rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch (argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list<string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return 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
ClaspLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
ClaspLayer::involveImports() {
ostream &out = __partGeneral;
for (string fn: ast->__rawImports)
{
std::ifstream file(fn);
if (!file) continue;
while(!file.eof()){
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
ClaspLayer::addRawScript(std::string&& script){
__partGeneral << script;
}
void
ClaspLayer::run() {
involveImports();
if (this->dataDFA){
this->dataDFA->print(__partGeneral);
}
if (this->dataCFA){
this->dataCFA->print(__partGeneral);
}
DominatorsTreeAnalysisProvider providerDominators;
providerDominators.run(this);
providerDominators.print(__partGeneral);
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
ctl.add("base", {}, program.str());
ctl.ground({{"base", {}}}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
this->handleSolution(model);
return true;
}, {});
if (result.satisfiable() == Gringo::SolveResult::Satisfiable) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process clasp data
for (auto q: __queries)
{
q.second->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
ClaspLayer::ModelFragment
ClaspLayer::query(const std::string& atom)
{
if (! __model.count(atom)){
return boost::none;
}
return ModelFragment(__model.equal_range(atom));
}
ScopePacked
ClaspLayer::pack(CodeScope* const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
size_t
ClaspLayer::getScopesCount() const{
return __registryScopes.size();
}
SymbolPacked
ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
ClaspLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{ScopedSymbol{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]};
};
std::string
ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
if (!symbol.categoryTransient) {
auto result = __indexSymbolNameHints.find(symbol);
return (result == __indexSymbolNameHints.end())? "" : result->second;
} else {
return "anonym(" + to_string(symbol.identifier) + ")";
}
}
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
IQuery*
ClaspLayer::registerQuery(IQuery *query, const QueryId& id) {
return __queries.emplace(id, query).first->second;
}
IQuery*
ClaspLayer::getQuery(const QueryId& id){
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
}
\ No newline at end of file
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
index 2ec48eb..6b891c7 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,191 +1,191 @@
/*
* File: targetabstract.h
* Author: pgess
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETABSTRACT_H
#define TARGETABSTRACT_H
#include "ast.h"
#include <boost/optional.hpp>
#include <map>
namespace xreate{ namespace compilation {
template <typename ConcreteTarget>
struct TargetInfo{
//typedef Result
//typedef Function
//typedef Scope
};
template<typename ConcreteTarget>
class Function;
template<typename ConcreteTarget>
class Target;
template<typename ConcreteTarget>
class Scope{
typedef typename TargetInfo<ConcreteTarget>::Scope Self;
public:
CodeScope* scope;
typename TargetInfo<ConcreteTarget>::Result
processSymbol(const Symbol& s){
CodeScope* scope = s.scope;
Self* self = function->getScope(scope);
if (self->__bindings.count(s.identifier)) {
return self->__bindings[s.identifier];
}
const Expression& declaration = CodeScope::getDeclaration(s);
if (!declaration.isDefined()){
assert(false); //for bindings there should be result already
}
return self->__bindings[s.identifier] = self->process(declaration);
}
typename TargetInfo<ConcreteTarget>::Result
processScope() {
if (raw) return *raw;
raw = process(scope->getBody());
return *raw;
}
// 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(CodeScope* codeScope, Function<ConcreteTarget>* f)
: scope(codeScope), function(f) {}
virtual ~Scope(){}
void
overrideBinding(typename TargetInfo<ConcreteTarget>::Result arg, const std::string& name){
assert(scope->__identifiers.count(name));
ScopedSymbol id{scope->__identifiers.at(name), VERSION_NONE};
__bindings[id] = arg;
//reset the result if any:
raw.reset();
}
void registerChildScope(std::shared_ptr<Self> scope){
__childScopes.push_back(scope);
}
void reset(){
__bindings.clear();
__childScopes.clear();
- raw == nullptr;
+ raw.reset();
}
protected:
Function<ConcreteTarget>* function=0;
std::map<ScopedSymbol, typename TargetInfo<ConcreteTarget>::Result> __bindings;
std::list<std::shared_ptr<Self>> __childScopes;
typename boost::optional<typename TargetInfo<ConcreteTarget>::Result> raw;
};
template<typename ConcreteTarget>
class Function{
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(CodeScope* scope){
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result){
return result.get();
}
}
std::shared_ptr<ConcreteScope> unit(new ConcreteScope(scope, this));
if (scope->__parent != nullptr){
getScope(scope->__parent)->registerChildScope(unit);
} else {
assert(!__entryScope);
__entryScope = unit;
}
if (!__scopes.emplace(scope, unit).second){
__scopes[scope] = unit;
}
return unit.get();
}
virtual Result
process(const std::vector<Result>& args)=0;
Target<ConcreteTarget>* man=0;
ManagedFnPtr __function;
protected:
std::map<CodeScope*, std::weak_ptr<ConcreteScope>> __scopes;
std::shared_ptr<ConcreteScope> __entryScope;
};
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;
};
}}
#endif /* TARGETABSTRACT_H */
diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/misc/serialization/expressionserializer.cpp
similarity index 99%
rename from cpp/src/serialization/expressionserializer.cpp
rename to cpp/src/misc/serialization/expressionserializer.cpp
index 447c7d1..d62a1cc 100644
--- a/cpp/src/serialization/expressionserializer.cpp
+++ b/cpp/src/misc/serialization/expressionserializer.cpp
@@ -1,318 +1,318 @@
/*
* expressionserializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
-#include "serialization/expressionserializer.h"
+#include "misc/serialization/expressionserializer.h"
#include <boost/utility.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <cmath>
using namespace std;
//using namespace boost::bimaps;
namespace xreate {
struct Index {
string name;
size_t degree; //count of parameters
unsigned char level; //level in expression tree (depth of tree layer)
bool operator< (const Index other) const{
if (name != other.name) return name < other.name;
if (degree != other.degree) return degree < other.degree;
if (name != other.name) return level < other.level;
return false;
}
};
class ExpressionSerializerPrivate {
//boost::bimap<Index, multiset_of<size_t>> __registry;
struct {
map<Index,size_t> left;
} __registry;
map<unsigned char, size_t> __range;
public:
void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){
if (!target) return;
switch (e.op){
case Operator::NONE: {
switch (e.__state) {
case Expression::NUMBER:
case Expression::STRING:
case Expression::IDENT : {
Index index;
if ((e.__state == Expression::NUMBER))
index = {std::to_string(e.getValueDouble()), 0, level};
else index = {e.getValueString(), 0, level};
if (!__registry.left.count(index)){
target = boost::none;
return;
}
size_t id = __registry.left.at(index);
size_t range = __range[level];
(*target) << make_pair(id, range);
return;
}
default: break;
}
break;
}
case Operator::CALL: {
Index index{e.getValueString(), e.operands.size(), level};
if(!__registry.left.count(index)){
target = boost::none;
return;
}
size_t id = __registry.left.at(index);
size_t range = __range[level];
(*target) << make_pair(id, range);
for (const Expression& operand: e.operands){
pack(operand, level+1, target);
}
return;
}
default: break;
}
assert(false && "Expression too complicate for serialization");
}
void registerExpression(const Expression&e, unsigned char level){
switch (e.op){
case Operator::CALL: {
Index index{e.getValueString(), e.operands.size(), level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
for (const Expression& operand: e.operands){
registerExpression(operand, level+1);
}
return;
}
case Operator::NONE: {
Index index;
switch (e.__state) {
case Expression::STRING:
case Expression::IDENT: {
index = {e.getValueString(), 0, level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
return;
}
case Expression::NUMBER: {
index = {std::to_string(e.getValueDouble()), 0, level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
return;
}
default: break;
}
break;
}
default: break;
}
assert(false && "Expression too complicate for serialization");
}
};
ExpressionSerializer::ExpressionSerializer()
: strategy(new ExpressionSerializerPrivate()){
}
ExpressionSerializer::~ExpressionSerializer() {
delete strategy;
}
void
ExpressionSerializer::registerExpression(const Expression&e){
if (e.isValid())
strategy->registerExpression(e, 0);
}
PackedExpression
ExpressionSerializer::getId(const Expression& e){
OptionalPackedExpression result(boost::in_place());
//move(PackedExpression())
strategy->pack(e, 0, result);
assert(result);
return move(*result);
}
OptionalPackedExpression
ExpressionSerializer::getIdOptional(const Expression& e) const{
OptionalPackedExpression result(boost::in_place());
//move(PackedExpression())
strategy->pack(e, 0, result);
return result;
}
ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){}
ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector<Expression>&& expressions)
: std::vector<Expression>(move(expressions)), serializer(*this){
size_t id =0;
for (const Expression& e: expressions){
__registry.emplace(serializer.getId(e), id++);
}
}
size_t
ExpressionSerializerIntegral::size() const{
return PARENT::size();
}
size_t
ExpressionSerializerIntegral::count(const Expression& e) const {
return (getIdOptional(e)? 1: 0);
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::begin() const {
return PARENT::begin();
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::end() const {
return PARENT::end();
}
size_t
ExpressionSerializerIntegral::getId(const Expression& e) const{
const OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
assert(exprPacked);
return __registry.at(*exprPacked);
}
boost::optional<size_t>
ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{
const OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
if (!exprPacked){
return boost::none;
}
return __registry.at(*exprPacked);
}
const Expression&
ExpressionSerializerIntegral::get(size_t id) const{
return at(id);
}
void
PackedExpression::operator<< (const std::pair<size_t, size_t>& value){
static const size_t sizeSizeT = sizeof(size_t);
const size_t& id = value.first;
const size_t& range = value.second;
int countSufficientBits = range <=1? 0 : ceil(log2(range));
if (0 < countRemainedBits && countRemainedBits < countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id >> (countSufficientBits - countRemainedBits);
countSufficientBits-=countRemainedBits;
countRemainedBits = 0;
}
if (countRemainedBits == 0) {
if (countSufficientBits == 0) return;
char* __storageNew = new char[size+sizeSizeT];
std::memcpy (__storageNew, __storage, size);
std::memset(__storageNew + size, 0, sizeSizeT);
delete[] __storage;
__storage = __storageNew;
size += sizeSizeT;
countRemainedBits = 8 * sizeSizeT;
}
if (countRemainedBits >= countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id << (countRemainedBits - countSufficientBits);
countRemainedBits -= countSufficientBits;
return;
}
assert("Unreachable block");
}
#if BOOST_VERSION <= 105500
PackedExpression::PackedExpression(const PackedExpression& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
}
#endif
PackedExpression::PackedExpression(PackedExpression&& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
other.__storage = nullptr;
}
bool
PackedExpression::operator==(const PackedExpression& other) const{
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) == 0 ;
}
return false;
}
bool
PackedExpression::operator<(const PackedExpression& other) const{
if (size < other.size) { return true; }
if (countRemainedBits < other.countRemainedBits) return true;
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) < 0 ;
}
return false;
}
bool
PackedExpression::operator!=(const PackedExpression& other) const{
return ! ((*this) == other);
}
PackedExpression::~PackedExpression() {
delete[] __storage;
}
//PackedExpression::PackedExpression (const PackedExpression& other)
// : size(other.size), countRemainedBits(other.countRemainedBits)
//{
// __storage = new char[size];
// std::memcpy (__storage, other.__storage, size);
//}
} /* namespace xreate */
\ No newline at end of file
diff --git a/cpp/src/serialization/expressionserializer.h b/cpp/src/misc/serialization/expressionserializer.h
similarity index 100%
rename from cpp/src/serialization/expressionserializer.h
rename to cpp/src/misc/serialization/expressionserializer.h
diff --git a/cpp/src/misc/xreatemanager-decorators.cpp b/cpp/src/misc/xreatemanager-decorators.cpp
new file mode 100644
index 0000000..242d45e
--- /dev/null
+++ b/cpp/src/misc/xreatemanager-decorators.cpp
@@ -0,0 +1,67 @@
+/*
+ * xreatemanager-decorators.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on July 16, 2017, 4:40 PM
+ */
+
+#include "misc/xreatemanager-decorators.h"
+#include "main/Parser.h"
+#include "pass/compilepass.h"
+#include "pass/adhocpass.h"
+#include "pass/cfapass.h"
+#include "pass/dfapass.h"
+#include "pass/interpretationpass.h"
+#include "pass/versionspass.h"
+
+namespace xreate {
+
+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(clasp);
+ clasp->run();
+}
+
+void
+XreateManagerDecoratorFull::initPasses(){
+ CFAPass* passCFG = new CFAPass(this);
+
+ //TODO is it really DFGPass needs CFGpass?
+ registerPass(new DFAPass(this), PassId::DFGPass, passCFG);
+ registerPass(passCFG, PassId::CFGPass);
+ this->registerPass(new AdhocPass(this), PassId::AdhocPass);
+ this->registerPass(new InterpretationPass(this), PassId::InterpretationPass);
+ this->registerPass(new VersionsPass(this), PassId::VersionsPass);
+}
+
+void*
+XreateManagerDecoratorFull::run() {
+ std::unique_ptr<CompilePass> compiler(new CompilePass(this));
+ compiler->run();
+
+ llvm->print();
+ llvm->initJit();
+ return llvm->getFunctionPointer(compiler->getEntryFunction());
+}
+
+} //namespace xreate
diff --git a/cpp/src/misc/xreatemanager-decorators.h b/cpp/src/misc/xreatemanager-decorators.h
new file mode 100644
index 0000000..942f23b
--- /dev/null
+++ b/cpp/src/misc/xreatemanager-decorators.h
@@ -0,0 +1,33 @@
+/*
+ * File: xreatemanager-decorators.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on July 16, 2017, 4:37 PM
+ */
+
+#ifndef XREATEMANAGER_DECORATORS_H
+#define XREATEMANAGER_DECORATORS_H
+
+#include "xreatemanager.h"
+
+namespace xreate {
+
+class XreateManagerDecoratorBase: public details::tier2::XreateManager{
+public:
+ void analyse();
+
+public:
+ virtual void prepareCode(std::string&& code);
+ virtual void prepareCode(FILE* code);
+};
+
+class XreateManagerDecoratorFull: public XreateManagerDecoratorBase {
+public:
+ void initPasses() override;
+ void* run();
+};
+
+}
+
+#endif /* XREATEMANAGER_DECORATORS_H */
+
diff --git a/cpp/src/misc/xreatemanager-modules.h b/cpp/src/misc/xreatemanager-modules.h
new file mode 100644
index 0000000..bff07cf
--- /dev/null
+++ b/cpp/src/misc/xreatemanager-modules.h
@@ -0,0 +1,110 @@
+/*
+ * File: PassManagerModular.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on June 22, 2017, 5:32 PM
+ */
+
+#ifndef PASSMANAGERMODULAR_H
+#define PASSMANAGERMODULAR_H
+
+#include "ast.h"
+#include "modules.h"
+#include "modules/Parser.h"
+#include "main/Parser.h"
+
+namespace xreate{
+
+template<class Parent>
+class XreateManagerDecoratorModules: public Parent{
+public:
+ XreateManagerDecoratorModules(): __registry(new ModulesRegistry()){}
+
+ void prepareCode(std::string&& code) override {
+ grammar::modules::Scanner scannerModules(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
+ std::list<std::string> listIncludedFiles;
+ parseModulesGrammar(scannerModules, listIncludedFiles);
+
+ grammar::main::Scanner scannerMain(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
+ parseMainGrammar(scannerMain, listIncludedFiles);
+ }
+
+ void prepareCode(FILE* code) override {
+ grammar::modules::Scanner scannerModules(code);
+ std::list<std::string> listIncludedFiles;
+ parseModulesGrammar(scannerModules, listIncludedFiles);
+
+ grammar::main::Scanner scannerMain(code);
+ parseMainGrammar(scannerMain, listIncludedFiles);
+ }
+
+private:
+ ModulesRegistry* __registry;
+
+ void parseModulesGrammar(grammar::modules::Scanner& scanner, std::list<std::string>& listIncludedFiles){
+ ModulesSolver solver(__registry);
+
+ grammar::modules::Parser parser(&scanner);
+ parser.Parse();
+ parser.module.__path = "";
+
+ solver.init("", parser.module);
+
+ std::list<std::string> modulesExternal = solver.run(parser.module);
+ std::string programBase = solver.__program.str();
+
+ for (const std::string module: modulesExternal){
+ parseModulesGrammar(module, programBase, listIncludedFiles);
+ }
+ }
+
+ void parseModulesGrammar(const std::string& path, std::string base, std::list<std::string>& listIncludedFiles){
+ FILE* input = fopen(path.c_str(), "r");
+ assert(input != nullptr);
+ grammar::modules::Scanner scanner(input);
+ grammar::modules::Parser parser(&scanner);
+ parser.Parse();
+ parser.module.__path = path;
+ fclose(input);
+
+ ModulesSolver solver(__registry);
+ solver.init(base, parser.module);
+
+ std::list<std::string>&& modulesExternal = solver.run(parser.module);
+ std::string programBase = solver.__program.str();
+
+ for (const std::string module: modulesExternal){
+ parseModulesGrammar(module, programBase, listIncludedFiles);
+ }
+
+ listIncludedFiles.push_back(path);
+ }
+
+ void parseMainGrammar(grammar::main::Scanner& scanner, std::list<std::string>& listIncludedFiles){
+ details::incomplete::AST* ast = new AST;
+
+ grammar::main::Parser parser(&scanner);
+ parser.root = ast;
+ parser.Parse();
+ assert(!parser.errors->count && "Parser errors");
+
+ for (auto file: listIncludedFiles){
+ FILE* fileContent = fopen(file.c_str(), "r");
+ grammar::main::Scanner scanner(fileContent);
+ grammar::main::Parser parser(&scanner);
+ parser.root = ast;
+ parser.Parse();
+ fclose(fileContent);
+
+ assert(!parser.errors->count && "Parser errors");
+ }
+
+ PassManager::prepare(ast->finalize());
+ }
+};
+
+} //end namespace xreate
+
+
+#endif /* PASSMANAGERMODULAR_H */
+
diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp
new file mode 100644
index 0000000..5866c8a
--- /dev/null
+++ b/cpp/src/modules.cpp
@@ -0,0 +1,164 @@
+/*
+ * modules.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on July 22, 2017, 5:13 PM
+ */
+
+#include "modules.h"
+#include "modules/Parser.h"
+#include "analysis/aux.h"
+#include <clingo/clingocontrol.hh>
+#include <boost/format.hpp>
+#include <regex>
+#include <boost/filesystem.hpp>
+#include <fstream>
+
+namespace fs = boost::filesystem;
+
+namespace xreate {
+void
+ModuleRecord::addModuleQuery(const Expression& query){
+ __queries.push_back(query);
+}
+
+void
+ModuleRecord::addControllerPath(const std::string& path){
+ __controllers.push_back(path);
+}
+
+void
+ModuleRecord::addDiscoveryPath(const std::string& path){
+ __discoveries.push_back(path);
+}
+
+void
+ModuleRecord::addProperty(const Expression& prop){
+ __properties.push_back(prop);
+}
+
+void
+ModulesSolver::loadControllers(const ModuleRecord& module){
+ for (const std::string& pathController: module.__controllers){
+ std::fstream fileContent(pathController);
+ __program << fileContent.rdbuf();
+ }
+}
+
+void
+ModulesSolver::extractProperties(const ModuleRecord& module){
+ unsigned int moduleId = __registry->getModuleHash(module.__path);
+ const std::string atomProperty = "bind_module";
+ boost::format formatProperty(atomProperty + "(%1%, %2%).");
+
+ for (const Expression& property: module.__properties){
+ std::list<std::string> reprProp = xreate::analysis::compile(property);
+ assert(reprProp.size()== 1);
+
+ __program << (formatProperty % moduleId % reprProp.front())
+ << std::endl;
+ }
+}
+
+void
+ModulesSolver::discoverModules(const ModuleRecord& moduleClient){
+ std::regex extXreate("\\.xreate$", std::regex::basic);
+
+ for(const std::string& path: moduleClient.__discoveries){
+ for(fs::directory_entry e: fs::recursive_directory_iterator(path)) {
+ if (fs::is_regular_file(e.status())){
+ if (!std::regex_search(e.path().string(), extXreate)) continue;
+
+ FILE* script = fopen(e.path().c_str(), "r");
+ grammar::modules::Scanner scanner(script);
+ grammar::modules::Parser parser(&scanner);
+ parser.Parse();
+ assert(!parser.errors->count && "Discovery errors");
+ parser.module.__path = e.path().c_str();
+
+ extractProperties(parser.module);
+ fclose(script);
+ }
+ }
+ }
+}
+
+void
+ModulesSolver::extractRequirements(const ModuleRecord& module){
+ const std::string atomQuery = "module_require";
+ boost::format formatProperty(atomQuery + "(%1%, %2%).");
+ unsigned int moduleId = __registry->getModuleHash(module.__path);
+
+ for (const Expression& query: module.__queries){
+ std::list<std::string> reprQuery = xreate::analysis::compile(query);
+ assert(reprQuery.size()== 1);
+
+ __program << (formatProperty % moduleId % reprQuery.front())
+ << std::endl;
+ }
+}
+
+void
+ModulesSolver::add(const std::string& base){
+ __program << base;
+}
+
+void
+ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){
+ add(programBase);
+ extractRequirements(module);
+ extractProperties(module);
+ loadControllers(module);
+ discoverModules(module);
+
+ std::cout << __program.str() << std::endl;
+}
+
+std::list<std::string>
+ModulesSolver::run(const ModuleRecord& module){
+ const std::string atomDecision = "module_include";
+ unsigned int moduleId = __registry->getModuleHash(module.__path);
+
+ std::list<std::string> result;
+ std::vector<char const *> args{"clingo", nullptr};
+ DefaultGringoModule moduleDefault;
+ Gringo::Scripts scriptsDefault(moduleDefault);
+ ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
+
+ ctl.add("base", {}, __program.str());
+ ctl.ground({{"base", {}}}, nullptr);
+ ctl.solve([&atomDecision, this, &result, moduleId](Gringo::Model const &model) {
+ for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
+ atom.print(std::cout);
+
+ if (std::strcmp(atom.name().c_str(), atomDecision.c_str())==0){
+ auto rowDecision = ClaspLayer::parse<unsigned int, unsigned int>(atom);
+
+ unsigned int moduleIdActual = std::get<0>(rowDecision);
+ if (moduleIdActual == moduleId){
+ result.push_back(__registry->getModuleNameByHash(std::get<1>(rowDecision)));
+ }
+ }
+ }
+ return true;
+ }, {});
+
+ return result;
+}
+
+const std::string&
+ModulesRegistry::getModuleNameByHash(unsigned int hash){
+ auto result = __registry.right.find(hash);
+ assert(result != __registry.right.end());
+
+ return result->second;
+}
+
+unsigned int
+ModulesRegistry::getModuleHash(const std::string& moduleName){
+ auto result = __registry.left.insert(Hash::left_value_type(moduleName, __registry.size()));
+
+ return result.first->second;
+}
+
+} //namespace xreate
diff --git a/cpp/src/modules.h b/cpp/src/modules.h
new file mode 100644
index 0000000..39c2e97
--- /dev/null
+++ b/cpp/src/modules.h
@@ -0,0 +1,76 @@
+/*
+ * File: modules.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on July 22, 2017, 5:11 PM
+ */
+
+#ifndef MODULES_H
+#define MODULES_H
+
+#include "ast.h"
+#include <boost/bimap.hpp>
+
+#ifndef FRIENDS_MODULES_TESTS
+#define FRIENDS_MODULES_TESTS
+#endif
+
+namespace xreate {
+class ModulesRegistry{
+public:
+ const std::string& getModuleNameByHash(unsigned int hash);
+ unsigned int getModuleHash(const std::string& moduleName);
+
+private:
+ typedef boost::bimap<std::string, unsigned int> Hash;
+ Hash __registry;
+};
+
+class ModulesSolver;
+
+class ModuleRecord {
+ FRIENDS_MODULES_TESTS
+ friend class ModulesSolver;
+
+public:
+ void addModuleQuery(const Expression& query);
+ void addControllerPath(const std::string& path);
+ void addDiscoveryPath(const std::string& path);
+ void addProperty(const Expression& prop);
+
+private:
+ std::list<Expression> __queries;
+ std::list<std::string> __controllers;
+ std::list<std::string> __discoveries;
+ std::list<Expression> __properties;
+
+public:
+ std::string __path;
+};
+
+class ModulesSolver{
+ FRIENDS_MODULES_TESTS
+
+public:
+ ModulesSolver(ModulesRegistry *registry): __registry(registry) {}
+
+ void loadControllers(const ModuleRecord& module);
+ void discoverModules(const ModuleRecord& moduleClient);
+
+ void extractProperties(const ModuleRecord& module);
+ void extractRequirements(const ModuleRecord& module);
+
+ void add(const std::string& base);
+
+ void init(const std::string& programBase, const ModuleRecord& module);
+ std::list<std::string> run(const ModuleRecord& module);
+
+private:
+ ModulesRegistry* __registry;
+
+public:
+ std::ostringstream __program;
+};
+} //end namespace xreate
+
+#endif /* MODULES_H */
\ No newline at end of file
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index ca6190a..18a7ed9 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,58 +1,58 @@
#include "abstractpass.h"
#include "attachments.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
using namespace std;
namespace xreate {
template<>
void defaultValue<void>(){}
void AbstractPassBase::finish(){}
AbstractPassBase::AbstractPassBase(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
{
if (__visitedSymbols.isCached(symbol))
return;
__visitedSymbols.setCachedValue(symbol);
const Expression& declaration = CodeScope::getDeclaration(symbol);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
process(declaration, context2, hintSymbol);
}
}
template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (expression.__state == Expression::COMPOUND){
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL){
processExpressionCall(expression, context);
}
return;
}
if (expression.__state == Expression::IDENT){
assert(context.scope);
processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
}
}
-}
\ No newline at end of file
+}
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index dfefc06..39c28de 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,194 +1,194 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
#include<iostream>
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
PassContext updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return context2;
}
~PassContext(){}
};
class AbstractPassBase {
public:
AbstractPassBase(PassManager* manager);
virtual void run()=0;
virtual void finish();
PassManager* man;
};
template<class Output>
Output defaultValue();
template<>
void defaultValue<void>();
template<class Output>
class SymbolCache: private std::map<Symbol, Output>{
public:
bool isCached(const Symbol& symbol){
return this->count(symbol);
}
Output setCachedValue(const Symbol& symbol, Output&& value){
(*this)[symbol] = value;
return value;
}
Output getCachedValue(const Symbol& symbol){
assert(this->count(symbol));
return this->at(symbol);
}
};
template<>
class SymbolCache<void>: private std::set<Symbol>{
public:
bool isCached(const Symbol& symbol){
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol& symbol){
this->insert(symbol);
}
void getCachedValue(const Symbol& symbol){
}
};
template<class Output>
class AbstractPass: public AbstractPassBase {
SymbolCache<Output> __visitedSymbols;
protected:
virtual Output processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol=""){
if (__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
const Expression& declaration = CodeScope::getDeclaration(symbol);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
Output&& result = process(declaration, context2, hintSymbol);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
Output processExpressionCall(const Expression& expression, PassContext context){
const std::string &calleeName = expression.getValueString();
std::list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
if (callees.size() == 1 && callees.front()){
return processFnCall(callees.front(), context);
} else {
for (const ManagedFnPtr& callee: callees){
processFnCallUncertain(callee, context);
}
return defaultValue<Output>();
}
}
SymbolCache<Output>& getSymbolCache(){
return __visitedSymbols;
}
public:
AbstractPass(PassManager* manager)
: AbstractPassBase(manager){}
virtual Output processFnCall(ManagedFnPtr function, PassContext context){
return defaultValue<Output>();
}
virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context)
{}
virtual void process(ManagedRulePtr rule)
{}
virtual Output process(ManagedFnPtr function)
{
PassContext context;
context.function = function;
return process(function->getEntryScope(), context);
}
virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
context.scope = scope;
return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
}
virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
if (expression.__state == Expression::IDENT){
assert(context.scope);
return processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
}
assert(false);
return defaultValue<Output>();
}
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while (rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while (f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol);
template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& hintSymbol);
}
#endif
//PROCESS FUNCTION:
// const Symbol& symbolFunction{0, function->getEntryScope()};
//
// if (__visitedSymbols.isCached(symbolFunction))
// return __visitedSymbols.getCachedValue(symbolFunction);
//
// PassContext context;
// context.function = function;
//
// Output&& result = process(function->getEntryScope(), context);
-// return __visitedSymbols.setCachedValue(symbolFunction, std::move(result));
\ No newline at end of file
+// return __visitedSymbols.setCachedValue(symbolFunction, std::move(result));
diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp
index 07801b6..80f3034 100644
--- a/cpp/src/pass/cfapass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,100 +1,100 @@
#include "cfapass.h"
#include "analysis/cfagraph.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate;
void
CFAPass::initSignatures(){
auto range = man->root->__interfacesData.equal_range(CFA);
for (auto i = range.first; i!= range.second; ++i){
__signatures.emplace(i->second.op, i->second);
}
}
void CFAPass::run(){
initSignatures();
return AbstractPass::run();
}
void
CFAPass::finish()
{
man->clasp->setCFAData(move(__context.graph));
return AbstractPass::finish();
}
void
CFAPass::processFnCall(ManagedFnPtr function, PassContext context)
{
ClaspLayer* clasp = man->clasp;
__context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
CFAPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){
ClaspLayer* clasp = man->clasp;
__context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCallUncertain(function, context);
}
void
CFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
ClaspLayer* clasp = man->clasp;
CodeScope* scopeParent = context.scope;
ScopePacked scopeId = clasp->pack(scope);
if (scopeParent){
__context.graph->addParentConnection(scopeId, clasp->pack(scopeParent));
} else {
__context.graph->addParentConnection(scopeId, context.function->getName());
}
//TOTEST scope annotations
//SECTIONTAG context gather scope annotations
__context.graph->addScopeAnnotations(scopeId, scope->tags);
__context.graph->addContextRules(scopeId, scope->contextRules);
return AbstractPass::process(scope, context, hintBlockDecl);
}
//TOTEST scope annotations via scheme
void
CFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
ClaspLayer* clasp = man->clasp;
if (expression.__state == Expression::COMPOUND){
Operator op= expression.op;
if (__signatures.count(op)) {
assert(expression.blocks.size());
for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
__context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFAPass::process(ManagedFnPtr function)
{
__context.graph->addFunctionAnnotations(function->getName(), function->getTags());
return AbstractPass::process(function);
}
CFAPass::CFAPass(PassManager* manager)
: AbstractPass(manager)
, __context{new xreate::analysis::CFAGraph(manager->clasp)}
-{}
\ No newline at end of file
+{}
diff --git a/cpp/src/pass/cfapass.h b/cpp/src/pass/cfapass.h
index a064c6d..b63e6a6 100644
--- a/cpp/src/pass/cfapass.h
+++ b/cpp/src/pass/cfapass.h
@@ -1,38 +1,38 @@
// Control Flow Graph determination pass
#ifndef CFGPASS_H
#define CFGPASS_H
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "clasplayer.h"
#include "abstractpass.h"
namespace xreate{namespace analysis {
class CFAGraph;
}}
namespace xreate {
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 process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
CFAPass(PassManager* manager);
void finish() override;
void run() override;
private:
struct {
xreate::analysis::CFAGraph* graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
}; }
#endif // CFGPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
index 49a957a..bee36eb 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,262 +1,262 @@
#include "pass/dfapass.h"
#include "analysis/dfagraph.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
using namespace std;
using namespace xreate::analysis;
namespace xreate {
class DfaExpressionProcessor {
std::vector<xreate::analysis::SymbolNode> operands;
std::vector<SymbolPacked> blocks;
const Expression expression;
xreate::analysis::SymbolNode result;
DFAPass * const pass;
const PassContext context;
public:
DfaExpressionProcessor(const Expression& expr, SymbolNode resInitial, DFAPass * const p, const PassContext c)
: expression(expr), result(resInitial), pass(p), context(c) {
operands.reserve(expression.getOperands().size());
for (const Expression &op : expression.getOperands()) {
SymbolAnonymous symbOp(op.id);
operands.push_back(DfaExpressionProcessor(op, symbOp, pass, context).process());
}
blocks.reserve(expression.blocks.size());
for (CodeScope* scope : expression.blocks) {
blocks.push_back(pass->process(scope, context));
}
}
SymbolNode
process() {
if (expression.__state == Expression::COMPOUND) {
processCompoundOp();
} else {
processElementaryOp();
}
applySignatureAnnotations();
applyInPlaceAnnotations();
return result;
}
private:
void
processElementaryOp() {
switch (expression.__state) {
case Expression::IDENT:
{
SymbolPacked symbFrom = pass->processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
SymbolPacked* symbTo = boost::get<SymbolPacked>(&result);
if (symbTo) {
pass->__context.graph->addConnection(*symbTo, SymbolNode(symbFrom), DFGConnection::STRONG);
} else {
result = SymbolNode(symbFrom);
}
break;
}
default: break;
}
}
void
processCompoundOp() {
switch (expression.op) {
//DEBT provide CALL processing
// case Operator::CALL: {
// const string &nameCalleeFunction = expression.getValueString();
//
// //TODO implement processFnCall/Uncertain
// list<ManagedFnPtr> variantsCalleeFunction = man->root->getFunctionVariants(nameCalleeFunction);
// if (variantsCalleeFunction.size()!=1) return;
// ManagedFnPtr function= variantsCalleeFunction.front();
//
// // set calling relations:
// CodeScope *scopeRemote = function->getEntryScope();
// std::vector<SymbolNode>::iterator nodeActual = cache.operands.begin();
// for (const std::string &identFormal: scopeRemote->__bindings){
// const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), VERSION_NONE};
//
// __context.graph->addConnection(clasp->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK);
// ++nodeActual;
// }
//
// //TODO add RET connection
// break;
// }
//MAP processing: apply PROTOTYPE relation
case Operator::MAP:
{
SymbolNode nodeFrom = operands.front();
SymbolPacked* nodeTo = boost::get<SymbolPacked>(&result);
assert(nodeTo);
pass->__context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::PROTOTYPE);
break;
}
default: break;
}
}
void
applySignatureAnnotations() {
if (pass->__signatures.count(expression.op)) {
const Expression &scheme = pass->__signatures.at(expression.op);
std::vector<SymbolNode>::iterator arg = operands.begin();
std::vector<Expression>::const_iterator tag = scheme.getOperands().begin();
//Assign scheme RET annotation
Expression retTag = *scheme.getOperands().begin();
if (retTag.__state != Expression::INVALID) {
pass->__context.graph->addAnnotation(result, move(retTag));
}
++tag;
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
pass->__context.graph->addAnnotation(*arg, Expression(*tag));
}
++arg;
++tag;
}
// TODO add possibility to have specific signature for a particular function
// if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
// string caption = expression.getValueString();
// operands.push_back(process(Expression(move(caption)), context, ""));
// }
}
}
void
applyInPlaceAnnotations() {
// write down in-place expression tags:
for (pair<std::string, Expression> tag : expression.tags) {
pass->__context.graph->addAnnotation(result, Expression(tag.second));
}
}
};
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, __context{new xreate::analysis::DFAGraph(manager->clasp)}
, clasp(manager->clasp)
{}
SymbolPacked
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) {
const SymbolPacked& symbRet = AbstractPass::process(scope, context, hintBlockDecl);
return symbRet;
}
SymbolPacked
DFAPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol) {
const Expression& declaration = CodeScope::getDeclaration(symbol);
const SymbolPacked& symbPacked = clasp->pack(symbol, hintSymbol);
DfaExpressionProcessor(declaration, symbPacked, this, context).process();
return symbPacked;
}
void
DFAPass::run() {
init();
return AbstractPass::run();
}
void
DFAPass::init() {
for (const Expression& scheme : man->root->__dfadata) {
__signatures.emplace(scheme.op, scheme);
}
}
void
DFAPass::finish() {
clasp->setDFAData(move(__context.graph));
}
template<>
SymbolPacked defaultValue(){
assert(false);
}
} //xreate namespace
//DEBT represent VersionaPass in declarative form using applyDependencies
// applyDependencies(expression, context, cache, decl);
//DEBT prepare static annotations and represent InterpretationPass in declarative form
// applyStaticAnnotations(expression, context, cache, decl);
//TODO Null ad hoc DFG implementation/None symbol
//DISABLEDFEATURE None value
// if (expression.isNone()){
// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
// }
// non initialized(SymbolInvalid) value
//void
//DFAPass::applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
// for (SymbolNode &op: cache.operands) {
// __context.graph->addDependencyConnection(cache.result, op);
// }
//
// for (SymbolNode &block: cache.blocks) {
// __context.graph->addDependencyConnection(cache.result, block);
// }
//
// switch(expression.__state) {
// case Expression::IDENT: {
// SymbolNode identSymbol = clasp->pack(Attachments::get<Symbol>(expression), context.function->getName() + ":" + expression.getValueString());
// __context.graph->addDependencyConnection(cache.result, identSymbol);
// }
//
// default: break;
// }
//}
//void
//DFAPass::applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
//
// switch(expression.__state) {
// case Expression::NUMBER:
// case Expression::STRING:
// __context.graph->addAnnotation(cache.result, Expression(Atom<Identifier_t>("static")));
// break;
//
// default: break;
// }
- //}
\ No newline at end of file
+ //}
diff --git a/cpp/src/passmanager-bare.cpp b/cpp/src/passmanager-bare.cpp
deleted file mode 100644
index 48c2715..0000000
--- a/cpp/src/passmanager-bare.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-
-#include "passmanager.h"
-#include <pass/abstractpass.h>
-#include "Parser.h"
-#include "clasplayer.h"
-
-#include <list>
-#include <stdio.h>
-
-using namespace xreate;
-using namespace std;
-
-PassManager*
-PassManager::prepareForCode(std::string&& code){
- Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
- return prepareForCode(&scanner);
-}
-
-PassManager*
-PassManager::prepareForCode(FILE* code){
- Scanner scanner(code);
- return prepareForCode(&scanner);
-}
-
-PassManager*
-PassManager::prepareForCode(Scanner* code){
- Parser parser(code);
- parser.Parse();
- assert(!parser.errors->count && "Parser errors");
-
- PassManager* man = new PassManager;
- AST* ast = new AST(parser.root);
-
- man->root = ast;
- man->clasp = new ClaspLayer();
-
- man->clasp->ast = man->root;
- man->llvm = new LLVMLayer(man->root);
-
- return man;
-}
-
-void
-PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
-{
- __passes.emplace(id, pass);
- __passDependencies.emplace(parent, pass);
-}
-
-AbstractPassBase*
-PassManager::getPassById(const PassId& id){
- assert(__passes.count(id));
- return __passes[id];
-}
-
-bool
-PassManager::isPassRegistered(const PassId& id){
- return __passes.count(id);
-}
-
-void
-PassManager::executePasses(){
- std::list<AbstractPassBase*> passes{nullptr};
- while (passes.size()){
- AbstractPassBase* parent = passes.front();
-
- auto range = __passDependencies.equal_range(parent);
-
- for (auto i=range.first; i!=range.second; ++i){
- AbstractPassBase* pass = i->second;
-
- pass->run();
- pass->finish();
-
- passes.push_back(pass);
- }
-
- passes.pop_front();
- }
-}
-
-
-
-PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager-full.cpp b/cpp/src/passmanager-full.cpp
deleted file mode 100644
index 5bb70b2..0000000
--- a/cpp/src/passmanager-full.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * passmanager-full.cpp
- *
- * Author: Volodymyr Melnychenko <v.melnychenko@xreate.org>
- * Created on January 27, 2017, 7:10 PM
- */
-
-#include "passmanager.h"
-#include "llvmlayer.h"
-#include "pass/compilepass.h"
-#include "pass/adhocpass.h"
-#include "pass/cfapass.h"
-#include "pass/dfapass.h"
-#include "pass/interpretationpass.h"
-#include "pass/versionspass.h"
-
-using namespace xreate;
-
-void PassManager::runWithoutCompilation(){
- if (flagIsProcessed) return;
-
- CFAPass* passCFG = new CFAPass(this);
-
- //TODO is it really DFGPass needs CFGpass?
- this->registerPass(new DFAPass(this), PassId::DFGPass, passCFG);
- this->registerPass(passCFG, PassId::CFGPass);
- this->registerPass(new AdhocPass(this), PassId::AdhocPass);
- this->registerPass(new InterpretationPass(this), PassId::InterpretationPass);
- this->registerPass(new VersionsPass(this), PassId::VersionsPass);
-
- this->executePasses();
-
- CompilePass::prepareQueries(clasp);
- clasp->run();
- flagIsProcessed = true;
-}
-
-void*
-PassManager::run()
-{
- runWithoutCompilation();
-
- CompilePass* compiler = new CompilePass(this);
- compiler->run();
-
- llvm->print();
- llvm->initJit();
- return llvm->getFunctionPointer(compiler->getEntryFunction());
-}
\ No newline at end of file
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
deleted file mode 100644
index 0e67ba0..0000000
--- a/cpp/src/passmanager.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef PASSMANAGER_H
-#define PASSMANAGER_H
-
-#include <string>
-#include <map>
-
-//stdio external
-struct _IO_FILE;
-typedef struct _IO_FILE FILE;
-
-class Scanner;
-
-namespace xreate {
-class AbstractPassBase;
-class ClaspLayer;
-class LLVMLayer;
-class AST;
-
-enum class PassId {
- CFGPass,
- CompilePass,
- DFGPass,
- EnvironmentTestsPass,
- LoggerPass,
- AdhocPass,
- RulesPass,
- InterpretationPass,
- VersionsPass
-};
-
-class PassManager
-{
-public:
- ~PassManager();
- void*run();
- void runWithoutCompilation();
- void executePasses();
- void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr);
- AbstractPassBase* getPassById(const PassId& id);
- bool isPassRegistered(const PassId& id);
- static PassManager* prepareForCode(std::string&& code);
- static PassManager* prepareForCode(FILE* code);
-
- ClaspLayer* clasp;
- LLVMLayer* llvm;
- AST* root;
-private:
- //typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
- //FILTERS_STORAGE __filters;
- std::map<PassId, AbstractPassBase*> __passes;
- std::multimap<AbstractPassBase*, AbstractPassBase*> __passDependencies;
- bool flagIsProcessed = false;
-
- static PassManager* prepareForCode(Scanner* code);
-}; }
-
-#endif
diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h
index 35db039..1991f66 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,84 +1,84 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "clasplayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
const ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
Query();
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/serialization.h b/cpp/src/serialization.h
index 08425af..af74e11 100644
--- a/cpp/src/serialization.h
+++ b/cpp/src/serialization.h
@@ -1,30 +1,30 @@
/*
* serialization.h
*
* Created on: 13 февр. 2016
* Author: pgess
*/
#ifndef SRC_SERIALIZATION_SERIALIZATION_H_
#define SRC_SERIALIZATION_SERIALIZATION_H_
-#include "serialization/expressionserializer.h"
+#include "misc/serialization/expressionserializer.h"
namespace xreate {
struct RequirementIntegralCode{};
template<class Requirements=void>
struct ExpressionSerialization {
typedef PackedExpression Code;
typedef ExpressionSerializer Serializer;
};
template<>
struct ExpressionSerialization<RequirementIntegralCode>{
typedef size_t Code;
typedef ExpressionSerializerIntegral Serializer;
};
}
#endif /* SRC_SERIALIZATION_SERIALIZATION_H_ */
diff --git a/cpp/src/xreatemanager.cpp b/cpp/src/xreatemanager.cpp
new file mode 100644
index 0000000..b7029c4
--- /dev/null
+++ b/cpp/src/xreatemanager.cpp
@@ -0,0 +1,123 @@
+/*
+ * xreatemanager.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on July 3, 2017, 6:03 PM
+ */
+
+#include "xreatemanager.h"
+#include "clasplayer.h"
+#include "misc/xreatemanager-decorators.h"
+#include "llvmlayer.h"
+#include "main/Parser.h"
+#include <assert.h>
+#include <list>
+
+namespace xreate {
+void
+PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
+{
+ __passes.emplace(id, pass);
+ __passDependencies.emplace(parent, pass);
+}
+
+AbstractPassBase*
+PassManager::getPassById(const PassId& id){
+ assert(__passes.count(id));
+ return __passes[id];
+}
+
+bool
+PassManager::isPassRegistered(const PassId& id){
+ return __passes.count(id);
+}
+
+void
+PassManager::executePasses(){
+ std::list<AbstractPassBase*> passes{nullptr};
+ while (passes.size()){
+ AbstractPassBase* parent = passes.front();
+
+ auto range = __passDependencies.equal_range(parent);
+
+ for (auto i=range.first; i!=range.second; ++i){
+ AbstractPassBase* pass = i->second;
+
+ pass->run();
+ pass->finish();
+
+ passes.push_back(pass);
+ }
+
+ passes.pop_front();
+ }
+}
+
+void
+PassManager::prepare(AST* ast){
+ root = ast;
+ clasp = new ClaspLayer();
+ clasp->ast = ast;
+ llvm = new LLVMLayer(ast);
+}
+
+PassManager::~PassManager(){}
+
+typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault;
+
+namespace details{ namespace tier2{
+
+XreateManager*
+XreateManager::prepare(std::string&& code){
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(std::move(code));
+ return man;
+}
+
+XreateManager*
+XreateManager::prepare(FILE* code){
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(code);
+ return man;
+}
+}}
+
+namespace details { namespace tier1 {
+
+XreateManager*
+XreateManager::prepare(std::string&& code){
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(std::move(code));
+ return man;
+}
+
+XreateManager*
+XreateManager::prepare(FILE* code){
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(code);
+ return man;
+}
+
+}}
+
+XreateManager*
+XreateManager::prepare(std::string&& code) {
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(std::move(code));
+ return man;
+}
+
+XreateManager*
+XreateManager::prepare(FILE* code){
+ auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
+
+ man->prepareCode(code);
+ return man;
+}
+
+}
diff --git a/cpp/src/xreatemanager.h b/cpp/src/xreatemanager.h
new file mode 100644
index 0000000..7ffb3c3
--- /dev/null
+++ b/cpp/src/xreatemanager.h
@@ -0,0 +1,122 @@
+#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 AbstractPassBase;
+class ClaspLayer;
+class LLVMLayer;
+class AST;
+
+enum class PassId {
+ CFGPass,
+ CompilePass,
+ DFGPass,
+ EnvironmentTestsPass,
+ LoggerPass,
+ AdhocPass,
+ RulesPass,
+ InterpretationPass,
+ VersionsPass
+};
+
+class PassManager{
+public:
+ void prepare(AST* ast);
+ void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr);
+ AbstractPassBase* getPassById(const PassId& id);
+ bool isPassRegistered(const PassId& id);
+ void executePasses();
+
+ virtual ~PassManager();
+
+ ClaspLayer* clasp;
+ LLVMLayer* llvm;
+ AST* root;
+
+private:
+ std::map<PassId, AbstractPassBase*> __passes;
+ std::multimap<AbstractPassBase*, AbstractPassBase*> __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 ac038d2..8611af2 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,50 +1,51 @@
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
main.cpp
+ modules.cpp
adhoc.cpp
attachments.cpp
ast.cpp
cfa.cpp
dfa.cpp
compilation.cpp
ExpressionSerializer.cpp
externc.cpp
context.cpp
types.cpp
vendorAPI/clangAPI.cpp
vendorAPI/xml2.cpp
vendorAPI/json.cpp
containers.cpp
context.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/ExpressionSerializer.cpp b/cpp/tests/ExpressionSerializer.cpp
index c5dc128..dae45e5 100644
--- a/cpp/tests/ExpressionSerializer.cpp
+++ b/cpp/tests/ExpressionSerializer.cpp
@@ -1,65 +1,65 @@
/*
* testExpressionSerializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
-#include "serialization/expressionserializer.h"
+#include "misc/serialization/expressionserializer.h"
#include "serialization.h"
#include "ast.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
TEST(ExpressionSerializer, pack1){
PackedExpression x;
x << std::make_pair(0xA1, 0x100);
size_t* storage = reinterpret_cast<size_t*> (*x);
ASSERT_EQ(0xA100000000000000, *storage);
x << std::make_pair(0x23456, 0x100000);
ASSERT_EQ(0xA123456000000000, *storage);
x << std::make_pair(0x7654321, 0x10000000);
ASSERT_EQ(0xA123456765432100, *storage);
x << std::make_pair(0xABBA, 0x10000);
storage = reinterpret_cast<size_t*> (*x);
ASSERT_EQ(0xA1234567654321AB, *storage);
ASSERT_EQ(0xBA00000000000000, *(storage+1));
}
TEST(ExpressionSerializer, serialize1){
Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))});
Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))});
ExpressionSerializer serializer(vector<Expression>{a, b});
PackedExpression packA = serializer.getId(a);
PackedExpression packB = serializer.getId(b);
PackedExpression packA2 = serializer.getId(a);
ASSERT_EQ(packA, packA2);
ASSERT_NE(packA, packB);
}
TEST(ExpressionSerializer, serialize2){
Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))});
Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))});
Expression c(Atom<Identifier_t>("c"));
typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Serializer;
Serializer serializer(vector<Expression>{a, b});
ASSERT_EQ(2, serializer.size());
ASSERT_EQ(1, serializer.count(a));
ASSERT_EQ(1, serializer.count(b));
ASSERT_EQ(0, serializer.count(c));
Serializer serializer2(move(serializer));
ASSERT_EQ(1, serializer2.count(a));
}
diff --git a/cpp/tests/adhoc.cpp b/cpp/tests/adhoc.cpp
index 55b586e..710fd4e 100644
--- a/cpp/tests/adhoc.cpp
+++ b/cpp/tests/adhoc.cpp
@@ -1,196 +1,194 @@
/*
* adhoc-exceptions.cpp
*
* Created on: Nov 19, 2015
* Author: pgess
*/
class Adhoc_pass_Adhoc1_Test;
#define FRIENDS_ADHOC \
friend class ::Adhoc_pass_Adhoc1_Test;
#include "ast.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "gtest/gtest.h"
#include <stdio.h>
#include <memory>
#include <sstream>
#include <stdlib.h>
#include "pass/adhocpass.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
using namespace xreate;
using namespace std;
TEST(Adhoc, ast_operatorAdhoc1){
- PassManager* man = PassManager::prepareForCode (
+ XreateManager* man = XreateManager::prepare (
"test = function:: int {\n"
" ad hoc exception(nonImplemented)\n"
"}");
Expression subject = man->root->findFunction("test")->getEntryScope()->getBody();
ASSERT_EQ(Operator::ADHOC, subject.op);
Expression exception = AdhocExpression(subject).getCommand();
ASSERT_EQ("exception", exception.getValueString());
}
TEST(Adhoc, ast_schemeAdhoc1){
- PassManager* man = PassManager::prepareForCode (
+ XreateManager* man = XreateManager::prepare (
"interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case (Error) {false}\n"
" case (Success) {true}\n"
" }\n"
" }");
assert(man->root->__interfacesData.count(ASTInterface::Adhoc));
Expression adhocData = man->root->__interfacesData.find(ASTInterface::Adhoc)->second;
ASSERT_EQ(Operator::SWITCH, adhocData.operands[0].op);
}
TEST(Adhoc, pass_Adhoc1){
- PassManager* man = PassManager::prepareForCode (
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare (
"interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case (Error) {false}\n"
" case (Success) {true}\n"
" }\n"
"}\n"
"main = function::int; entry {0} \n"
);
- man->runWithoutCompilation();
+ man->analyse();
AdhocPass* pass = reinterpret_cast<AdhocPass* >(man->getPassById(PassId::AdhocPass));
EXPECT_TRUE(pass->__schemes.size() > 0);
AdhocScheme* scheme = pass->__schemes.begin()->second;
EXPECT_EQ("expectNoErrors", scheme->getName());
}
TEST(Adhoc, full_1){
- PassManager* man = PassManager::prepareForCode (
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare (
+ " import raw (\"core/control-context.lp\").\n"
" interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case (error) {false}\n"
" case (success) {true}\n"
" }\n"
" }\n"
" test1 = pre function {\n"
" context:: expectNoErrors."
" ad hoc success\n"
" }"
"main = function::bool;entry {\n"
" test1()\n"
" }");
bool (*main)() = (bool (*)()) man->run();
bool result = main();
ASSERT_EQ(true, result);
}
TEST(Adhoc, full_2){
- PassManager* man = PassManager::prepareForCode (
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare (
+ " import raw (\"core/control-context.lp\").\n"
" interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case (error) {false}\n"
" case (success) {true}\n"
" }\n"
" pre function expectErrors:: bool {\n"
" case (error) {true}\n"
" case (success) {false}\n"
" }\n"
" }\n"
" test1 = pre function {\n"
" context:: expectNoErrors."
" ad hoc success\n"
" }\n"
" test2 = pre function {\n"
" context:: expectErrors."
" ad hoc success\n"
" }"
"main = function::bool;entry {\n"
" test1() != test2()\n"
"}");
bool (*main)() = (bool (*)()) man->run();
bool result = main();
ASSERT_EQ(true, result);
}
//TODO adhoc type. FDecl sets wrong type in prefunc case(invalid type))
TEST(Adhoc, full_contextExpectNoErrrors){
- PassManager* man = PassManager::prepareForCode (
- "import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare (
+ "import raw (\"core/control-context.lp\").\n"
"interface(extern-c){\n"
" xml2 = library:: pkgconfig(\"libxml-2.0\").\n"
" \n"
" include {\n"
" xml2 = [\"stdlib.h\"]\n"
" }.\n"
"}"
"interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case (error) {false}\n"
" case (success) {true}\n"
" }\n"
"}\n"
"expectErrorCode = pre function(x::int){\n"
" if (x==0)::undef {ad hoc success}\n"
" else {ad hoc error}\n"
"}\n"
"main = function::bool; entry {\n"
" context:: expectNoErrors."
" expectErrorCode(system(\"ls -la\"))\n"
"}" );
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(1, main());
}
//DEBT Implement compilation of switch adhoc
TEST(Adhoc, ast_switchAdhoc1){
- PassManager* man = PassManager::prepareForCode (
+ XreateManager* man = XreateManager::prepare (
"test1 = function:: bool {\n"
" x = 0. \n"
" switch ad hoc (x:: errors)\n"
" case (error) {0}\n"
" case (success) {1}\n"
"\n"
"}"
);
Expression eSwitch = man->root->findFunction("test1")->getEntryScope()->getBody();
EXPECT_EQ(Operator::SWITCH_ADHOC, eSwitch.op);
EXPECT_EQ(3, eSwitch.operands.size());
EXPECT_EQ(1, eSwitch.tags.size());
EXPECT_EQ("errors", eSwitch.tags.begin()->first);
Expression eCondition = eSwitch.getOperands()[0];
EXPECT_EQ("x", eCondition.getValueString());
-}
-
-
+}
\ No newline at end of file
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index d1fb31f..0720184 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,68 +1,68 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
-#include "passmanager.h"
-#include "Parser.h"
+#include "xreatemanager.h"
+#include "main/Parser.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) {
- PassManager* man = PassManager::prepareForCode
+ 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){
- PassManager* man = PassManager::prepareForCode(R"Code(
+ XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
a = b:: int.
b = 8:: int.
a
}
)Code");
}
TEST(AST, syntax_operatorIndex){
- PassManager* man = PassManager::prepareForCode(R"Code(
+ XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
b = a[1].
b
}
)Code");
}
TEST(AST, DISABLED_InterfacesDataDFA){
}
TEST(AST, DISABLED_InterfacesDataExtern){
}
//TODO xreate.atg: replace all Type<> as ExprAnnotations<>
diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp
index 42f7c4f..5d4f84a 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,119 +1,119 @@
/*
* testsCFG.cpp
*
* Created on: Jul 17, 2015
* Author: pgess
*/
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "pass/cfapass.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "gtest/gtest.h"
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
using namespace xreate;
using namespace std;
TEST(CFA, testFunctionAnnotationsClasp){
string&& program =
"f2 = function::int; annotationF2 {\n"
" 0\n"
"}\n"
"\n"
"f1 = function:: int; entry; annotationF1 {\n"
" f2() + 10\n"
"}";
- PassManager* man = PassManager::prepareForCode(move(program));
- man->runWithoutCompilation();
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(program));
+ man->analyse();
ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1");
int countNoneValue = 0;
if (answer) countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
answer = man->clasp->query("annotationF2");
countNoneValue = 0;
if (answer) countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
}
TEST(CFA, testLoopContextExists){
- PassManager* man = PassManager::prepareForCode (
+ 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"
"}"
"case context:: annotation1 {"
" f1 = function::int {\n"
" x = 0:: int. "
" x\n"
" }"
"}"
);
- man->runWithoutCompilation();
+ man->analyse();
ClaspLayer::ModelFragment model = man->clasp->query("annotation1");
ScopePacked scopeIdActual = std::get<0>(ClaspLayer::parse<ScopePacked>(model->first->second));
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
const Expression& exprSum = scopeEntry->getDeclaration(scopeEntry->getSymbol("sum"));
CodeScope* scopeExpected = exprSum.blocks.front();
ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected);
ASSERT_EQ(scopeIdExpected, scopeIdActual);
}
TEST(CFA, CFGRoots){
std::string program =
R"CODE(
main = function::int{a()+ b()}
a= function::int {c1() + c2()}
b= function::int {c2()}
c1=function::int{0}
c2=function::int{0}
)CODE";
- boost::scoped_ptr<PassManager> manager
- (PassManager::prepareForCode(move(program)));
+ boost::scoped_ptr<XreateManager> manager
+ (XreateManager::prepare(move(program)));
manager->registerPass(new CFAPass(manager.get()) , PassId::CFGPass);
manager->executePasses();
manager->clasp->run();
DominatorsTreeAnalysisProvider domProvider;
domProvider.run(manager->clasp);
DominatorsTreeAnalysisProvider::Dominators expectedFDom= {
{0, {0, 9}}
,{1, {1, 4}}
,{2, {7, 8}}
,{3, {2, 3}}
,{4, {5, 6}}
};
DominatorsTreeAnalysisProvider::Dominators expectedPostDom= {
{0, {5, 6}}
,{1, {3, 4}}
,{2, {8, 9}}
,{3, {1, 2}}
,{4, {7, 10}}
};
ASSERT_EQ(expectedFDom, domProvider.getForwardDominators());
ASSERT_EQ(expectedPostDom, domProvider.getPostDominators());
}
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index 95b96b6..8c00e14 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,37 +1,37 @@
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "gtest/gtest.h"
using namespace xreate;
//DEBT implement no pkgconfig ways to link libs
//TOTEST FunctionUnit::compileInline
TEST(Compilation, DISABLED_functionInline1){
}
TEST(Compilation, functionEntry1){
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(
"func1 = function(a:: int):: int {a+8} \
func2 = function::int; entry {12 + func1(4)} \
"));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = entry();
ASSERT_EQ(24, answer);
}
TEST(Compilation, full_IFStatementWithVariantType){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
"Color = type variant (RED, BLUE, GREEN).\n"
"\n"
" main = function(x::int):: bool; entry {\n"
" color = if (x == 0 )::Color {RED} else {BLUE}.\n"
" if (color == BLUE)::bool {true} else {false}\n"
" }"
);
bool (*main)(int) = (bool (*)(int)) man->run();
ASSERT_FALSE(main(0));
ASSERT_TRUE(main(1));
}
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 7037a8d..75fbfc5 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,109 +1,109 @@
/*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess
*/
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "query/containers.h"
-#include "Parser.h"
+#include "main/Parser.h"
#include "gtest/gtest.h"
using namespace std;
-using namespace xreate;
-using namespace containers;
+using namespace xreate::grammar::main;
+using namespace xreate::containers;
TEST(Containers, ListAsArray){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
main = function(x:: int):: int;entry {
a = [1, 2, 3]:: [int].
a[x]
}
)Code" );
void* mainPtr = man->run();
int (*main)(int) = (int (*)(int))mainPtr;
ASSERT_EQ(2, main(1));
delete man;
}
TEST(Containers, ListAsArray2){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
// CONTAINERS
interface(dfa) {
operator map:: (op(seqaccess)) -> impl(solid).
operator list_range:: ()->impl(on_the_fly).
operator list:: ()->impl(solid).
operator fold:: (op(seqaccess)).
operator index:: (op(randaccess)).
}
- import raw("core/containers.lp")
+ import raw("core/containers.lp").
main = function:: int;entry {
a= [1, 2, 3]:: [int].
b= loop map(a->el:: int):: [int]{
2 * el
}.
sum = loop fold(b->el:: int, 0->acc):: int {
acc + el
}.
sum
}
)Code" );
void* mainPtr = man->run();
int (*main)() = (int (*)())mainPtr;
ASSERT_EQ(12, main());
delete man;
}
TEST(Containers, ContanierLinkedList1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
- AST& ast = parser.root;
- CodeScope* body = ast.findFunction("test")->getEntryScope();
+ AST* ast = parser.root->finalize();
+ CodeScope* body = ast->findFunction("test")->getEntryScope();
const Symbol symb_chilrenRaw{body->getSymbol("childrenRaw"), body};
containers::ImplementationLinkedList iLL(symb_chilrenRaw);
ASSERT_EQ(true, static_cast<bool>(iLL));
ASSERT_EQ("next", iLL.fieldPointer);
Implementation impl = Implementation::create(symb_chilrenRaw);
ASSERT_NO_FATAL_FAILURE(impl.extract<ON_THE_FLY>());
ImplementationRec<ON_THE_FLY> recOnthefly = impl.extract<ON_THE_FLY>();
ASSERT_EQ(symb_chilrenRaw, recOnthefly.source);
}
TEST(Containers, Implementation_LinkedListFull){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
ASSERT_EQ(17, answer);
fclose(input);
}
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
index 796fee1..92b19fc 100644
--- a/cpp/tests/context.cpp
+++ b/cpp/tests/context.cpp
@@ -1,496 +1,494 @@
/*
* frame-context.cpp
*
* Created on: Dec 3, 2015
* Author: pgess
*/
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "query/context.h"
#include "gtest/gtest.h"
#include <iostream>
#include <boost/scoped_ptr.hpp>
using namespace xreate;
TEST(Context, frame_Context1){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" compute = function::int {\n"
" 0\n"
" }\n"
" computeFast = function:: int {\n"
" context:: computation(fast).\n"
" compute()\n"
" }\n"
" computePrecisely = function:: int {\n"
" context:: computation(precise). \n"
" compute()\n"
" }\n"
"test = function(cmnd:: int):: int; entry {\n"
" context:: arithmetic(iee754). \n"
" if (cmnd > 0)::int {computePrecisely()} else {computeFast()} \n"
"}\n"
);
ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
- man->runWithoutCompilation();
+ man->analyse();
CodeScope* scopeTestC = man->root->findFunction("compute")->getEntryScope();
const Domain& context = query->getContext(man->clasp->pack(scopeTestC));
int contextSize = context.size();
EXPECT_EQ(1, contextSize); //arithmetic(iee754)
}
TEST(Context, contextAsRequirementSuccessful1){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context::safe {\n"
" funcSensitive = function::int {\n"
" 0\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: safe; test.\n"
" funcSensitive()\n"
" }\n"
);
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(0, main());
}
TEST(Context, contextAsRequirementFailed){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context::safe {\n"
" funcSensitive = function::int {\n"
" 0\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: non_safe; test.\n"
" funcSensitive()\n"
" }\n"
);
ASSERT_DEATH(man->run(), "findFunction");
}
TEST(Context, ContextPropagationNested){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context::safe {\n"
" square = function(x:: int) ::int {\n"
" x * x\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: safe; test.\n"
" range = [1..10]:: [int]. \n"
" loop fold(range->x::int, 0->acc):: int { \n"
" acc + square(x) \n"
" } \n"
" }\n"
);
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(385, main());
}
TEST(Context, ContextPropagationNestedInterfunction){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context::toMillimeters {\n"
" convertConcrete = function(source:: num)::num {\n"
" 10 * source \n"
" }\n"
" }\n"
" case context::toInches {\n"
" convertConcrete = function(source:: num)::num {\n"
" 2 * source \n"
" }\n"
" }\n"
"convert= function(source:: num):: num { \n"
"convertConcrete(source) \n"
"} \n"
"test = function(source:: num):: num; entry {\n"
" context:: toMillimeters.\n"
" convert(1)\n"
"}\n" );
int (*main)(int) = (int (*)(int)) man->run();
ASSERT_EQ(10, main(1));
}
TEST(Context, full_ContextBasedFunctionSpecialization){
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context::toMillimeters {\n"
" convert = function(source:: num)::num {\n"
" 10 * source \n"
" }\n"
" }\n"
" case context::toInches {\n"
" convert = function(source:: num)::num {\n"
" 2 * source \n"
" }\n"
" }\n"
"test = function(vrnt:: int)::int; entry {\n"
" switch(vrnt):: int\n"
" case (0) {\n"
" context:: toMillimeters.\n"
" convert(1)\n"
" }\n"
"\n"
" case (1) {\n"
" context:: toInches.\n"
" convert(1)\n"
" }\n"
" case default {0}\n"
" }" );
int (*main)(int) = (int (*)(int)) man->run();
ASSERT_EQ(10, main(0));
ASSERT_EQ(2, main(1));
}
TEST(Context, full_RuleContext){
/*
"rule context:: childs(Child)\n"
" case artefact(Item)\n"
" {\n"
" artefact_depends(Item, Child)\n"
" }";
*/
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\").\n"
" case context:: toMilli {\n"
" convert = function(length::int)::int{\n"
" 10 * length\n"
" }\n"
" }\n"
"\n"
" case context:: toCenti {\n"
" convert = function(length::int)::int{\n"
" length\n"
" }\n"
" }\n"
"\n"
" main=function::int; entry {\n"
" context:: output(milli).\n"
"\n"
" rule context::toMilli\n"
" case (output(milli)) {truth}\n"
"\n"
" convert(1)\n"
" }" );
man->clasp->addRawScript("truth.");
int (*entry)() = (int (*)()) man->run();
ASSERT_EQ(10, entry());
}
TEST(Context, full_InheritedRuleContext){
- PassManager* man = PassManager::prepareForCode(
-" import raw (\"core/control-context.lp\") \n"
+ XreateManager* man = XreateManager::prepare(
+" import raw (\"core/control-context.lp\"). \n"
" case context:: toMilli {\n"
" convert = function(length::int)::int{\n"
" 10 * length\n"
" }\n"
" }\n"
" case context:: toCenti {\n"
" convert = function(length::int)::int{\n"
" length\n"
" }\n"
" }\n"
"\n"
"main = function(comm:: num)::num; entry{\n"
" rule context::X case (output(X)) {truth}\n"
"\n"
" switch (comm)::num \n"
" case (0) {\n"
" context:: output(toMilli).\n"
" convert(1)\n"
" }\n"
" case default {\n"
" context:: output(toCenti).\n"
" convert(1)\n"
" }\n"
" }");
man->clasp->addRawScript("truth.");
int (*entry)(int) = (int (*)(int)) man->run();
ASSERT_EQ(10, entry(0));
ASSERT_EQ(1, entry(1));
}
TEST(Context, full_LateContext){
- PassManager* man = PassManager::prepareForCode(
- "import raw (\"core/control-context.lp\")\n"
-
- " convert = function(length:: num)::num{\n"
- " 0\n"
- " }\n"
-
- "case context:: milli {\n"
- " convert = function(length:: num)::num{\n"
- " 1000 * length\n"
- " }\n"
- "}\n"
- "\n"
- "case context:: centi {\n"
- " convert = function(length:: num)::num{\n"
- " 100 * length\n"
- " }\n"
- "}\n"
- "\n"
- "calculate = function(length:: num)::num {\n"
- " convert(length)\n"
- "}\n"
- "\n"
- "main = function(com:: num):: num; entry {\n"
- " switch (com):: num \n"
- " case (0) {\n"
- " context:: milli.\n"
- " calculate(1)\n"
- " }\n"
- "\n"
- " case default{\n"
- " context:: centi. \n"
- " calculate(1)\n"
- " }\n"
- "}");
-
- man->runWithoutCompilation();
- ContextQuery* queryContext = reinterpret_cast<ContextQuery*>(man->clasp->getQuery(QueryId::ContextQuery));
- Expression exprSwitch = man->root->findFunction("main")->__entry->getBody();
- CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front();
- ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
- const Domain& domDefault = queryContext->getContext(blockDefaultId);
- ASSERT_EQ(1, domDefault.count(Expression(Atom<Identifier_t>("centi"))));
-
- std::list<ManagedFnPtr> variants = man->root->getFunctionVariants("convert");
- for (ManagedFnPtr f: variants){
- const Expression guard = f->guardContext;
- bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid());
- ASSERT_TRUE(result);
- }
-
- const FunctionDemand& demMain = queryContext->getFunctionDemand("main");
- ASSERT_EQ(0, demMain.size());
-
- const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate");
- ASSERT_EQ(1, demCalculate.size());
-
- int (*entry)(int) = (int (*)(int)) man->run();
- ASSERT_EQ(1000, entry(0));
- ASSERT_EQ(100, entry(1));
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
+ "import raw (\"core/control-context.lp\").\n"
+
+ " convert = function(length:: num)::num{\n"
+ " 0\n"
+ " }\n"
+
+ "case context:: milli {\n"
+ " convert = function(length:: num)::num{\n"
+ " 1000 * length\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "case context:: centi {\n"
+ " convert = function(length:: num)::num{\n"
+ " 100 * length\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "calculate = function(length:: num)::num {\n"
+ " convert(length)\n"
+ "}\n"
+ "\n"
+ "main = function(com:: num):: num; entry {\n"
+ " switch (com):: num \n"
+ " case (0) {\n"
+ " context:: milli.\n"
+ " calculate(1)\n"
+ " }\n"
+ "\n"
+ " case default{\n"
+ " context:: centi. \n"
+ " calculate(1)\n"
+ " }\n"
+ "}");
+
+ man->analyse();
+ ContextQuery* queryContext = reinterpret_cast<ContextQuery*>(man->clasp->getQuery(QueryId::ContextQuery));
+ Expression exprSwitch = man->root->findFunction("main")->__entry->getBody();
+ CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front();
+ ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
+ const Domain& domDefault = queryContext->getContext(blockDefaultId);
+ ASSERT_EQ(1, domDefault.count(Expression(Atom<Identifier_t>("centi"))));
+
+ std::list<ManagedFnPtr> variants = man->root->getFunctionVariants("convert");
+ for (ManagedFnPtr f: variants){
+ const Expression guard = f->guardContext;
+ bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid());
+ ASSERT_TRUE(result);
+ }
+
+ const FunctionDemand& demMain = queryContext->getFunctionDemand("main");
+ ASSERT_EQ(0, demMain.size());
+
+ const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate");
+ ASSERT_EQ(1, demCalculate.size());
+
+ int (*entry)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(1000, entry(0));
+ ASSERT_EQ(100, entry(1));
}
TEST(Context, loopContextExists){
- PassManager* man = PassManager::prepareForCode (
- "import raw (\"core/control-context.lp\")\n"
+ XreateManager* man = XreateManager::prepare (
+ "import raw (\"core/control-context.lp\").\n"
"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"
"}"
"case context:: annotation1 {"
" f1 = function::int {\n"
" x = 0:: int. "
" x\n"
" }"
"}"
);
man->run();
}
TEST(Context, pathDependentContext){
std::string program =
R"CODE(
-import raw("core/control-context.lp")
+import raw("core/control-context.lp").
convert = function(length:: num) :: num {
0
}
case context:: convert(milli, meters) {
convert = function(length:: num) :: num {
1000 * length
}
}
case context:: convert(centi, meters) {
convert = function(length:: num) :: num {
100 * length
}
}
case context:: convert(centi, kilo) {
convert = function(length:: num) :: num {
100000 * length
}
}
case context:: convert(milli, kilo) {
convert = function(length:: num) :: num {
1000000 * length
}
}
main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{
switch (unitsInput)::num
case (0) {
test_fromMilli(value, unitsOutput)
}
case (1) {
test_fromCenti(value, unitsOutput)
}
case default {0}
}
test_fromCenti = function(value::num, output::num)::num{
context:: input(centi).
switch(output):: num
case (0) {
toMeters(value)
}
case (1) {
toKilo(value)
}
case default {0}
}
test_fromMilli = function(value::num, output::num)::num{
context:: input(milli).
switch(output):: num
case (0) {
toMeters(value)
}
case (1) {
toKilo(value)
}
case default {0}
}
toMeters = function(value::num)::num {
rule context:: convert(X, meters) case (input(X)) {truth}
doConvert(value)
}
toKilo = function(value::num)::num {
rule context:: convert(X, kilo) case (input(X)) {truth}
doConvert(value)
}
doConvert = function(value::num)::num{
convert(value)
})CODE";
- boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
+ boost::scoped_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
man->clasp->addRawScript("truth.");
- man->runWithoutCompilation();
+ man->analyse();
int (*test)(int, int, int) = (int (*)(int, int, int))man->run();
enum {INPUT_MILLI, INPUT_CENTI};
enum {OUTPUT_METERS, OUTPUT_KILO};
ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO));
ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS));
}
//TODO recover context loop and enable the test
TEST(Context, DISABLED_full_LoopContext){
-
- PassManager* man = PassManager::prepareForCode(
- " import raw (\"core/control-context.lp\")\n"
- " case context:: a {\n"
- " print = function:: string {\n"
- " \"a\"\n"
- " }}\n"
- "\n"
- " case context:: b {\n"
- " print = function:: string {\n"
- " \"b\"\n"
- " }}\n"
- "\n"
- " case context:: c {\n"
- " print = function:: string {\n"
- " \"c\"\n"
- " }}\n"
- "\n"
- " case context:: d {\n"
- " print = function:: string {\n"
- " \"d\"\n"
- " }}\n"
- "\n"
- " start = function(command::int)::string; entry {\n"
- " switch (command) :: string \n"
- " case (0) {\n"
- " context:: print(a); print(b); print(d).\n"
- "\n"
- " loop context (\"print\") {\n"
- " print()\n"
- " }\n"
- " }\n"
- "\n"
- " case default {\n"
- " context:: print(c).\n"
- " loop context (\"print\") {\n"
- " print()\n"
- " }\n"
- " }\n"
- " }");
-
-
- char* (*main)(int) =(char* (*)(int)) man->run();
- ASSERT_STREQ("c", main(1));
- ASSERT_STREQ("a", main(0));
-}
-
+ XreateManager* man = XreateManager::prepare(
+ " import raw (\"core/control-context.lp\")\n"
+ " case context:: a {\n"
+ " print = function:: string {\n"
+ " \"a\"\n"
+ " }}\n"
+ "\n"
+ " case context:: b {\n"
+ " print = function:: string {\n"
+ " \"b\"\n"
+ " }}\n"
+ "\n"
+ " case context:: c {\n"
+ " print = function:: string {\n"
+ " \"c\"\n"
+ " }}\n"
+ "\n"
+ " case context:: d {\n"
+ " print = function:: string {\n"
+ " \"d\"\n"
+ " }}\n"
+ "\n"
+ " start = function(command::int)::string; entry {\n"
+ " switch (command) :: string \n"
+ " case (0) {\n"
+ " context:: print(a); print(b); print(d).\n"
+ "\n"
+ " loop context (\"print\") {\n"
+ " print()\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " case default {\n"
+ " context:: print(c).\n"
+ " loop context (\"print\") {\n"
+ " print()\n"
+ " }\n"
+ " }\n"
+ " }");
+
+
+ char* (*main)(int) =(char* (*)(int)) man->run();
+ ASSERT_STREQ("c", main(1));
+ ASSERT_STREQ("a", main(0));
+}
\ No newline at end of file
diff --git a/cpp/tests/dfa.cpp b/cpp/tests/dfa.cpp
index c8bc714..53deb4e 100644
--- a/cpp/tests/dfa.cpp
+++ b/cpp/tests/dfa.cpp
@@ -1,14 +1,14 @@
/*
* DFGtests.cpp
*
* Created on: Jul 23, 2015
* Author: pgess
*/
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
//DEBT dfa tests: dfa scheme, dfa scheme + return value annoation (example: script/testpass/containers...)
diff --git a/cpp/tests/effects-versions.cpp b/cpp/tests/effects-versions.cpp
index 3ca9fb4..95e22c7 100644
--- a/cpp/tests/effects-versions.cpp
+++ b/cpp/tests/effects-versions.cpp
@@ -1,276 +1,276 @@
/*
* Created on: Dec 16, 2016
* Author: pgess
*/
#include "pass/versionspass.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "gtest/gtest.h"
using namespace xreate;
TEST(Effects, syntax_versions_1){
- PassManager* man = PassManager::prepareForCode(R"Code(
+ XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
x= b[8].
b = 5:: num.
x{1} = a:: num.
x{1} + a
}
)Code");
}
TEST(Effects, analysis_versions_1){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{0}= 3:: int.
x{1} = x{0} + 1.
x{1}
}
)Code");
VersionsPass* pass = new VersionsPass(man);
pass->run();
VersionsGraph graph = pass->getResultGraph();
ASSERT_TRUE(graph.validate());
}
TEST(Effects, analysis_versions_2){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
test= function(a:: num):: num; entry {
x{0}= 3:: int.
b = [1, 2, x{0}].
x{1} = b[2].
x{1} + a
}
)Code");
VersionsPass* pass = new VersionsPass(man);
pass->run();
VersionsGraph graph = pass->getResultGraph();
ASSERT_TRUE(graph.validate());
}
TEST(Effects, analysis_versions_2_1_fail){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
test= function(a:: num):: num; entry {
x{0}= 5:: int.
b = x{0}.
x{1} = 2.
b + x{1}
}
)Code");
VersionsPass* pass = new VersionsPass(man);
pass->run();
VersionsGraph graph = pass->getResultGraph();
graph.__debug_print(std::cout);
ASSERT_FALSE(graph.validate());
}
TEST(Effects, analysis_versions_2_2){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
test= function(a:: num):: num; entry {
x{0}= 5:: int.
b = intrinsic copy(x{0}).
x{1} = 2.
b + x{1}
}
)Code");
VersionsPass* pass = new VersionsPass(man);
pass->run();
VersionsGraph graph = pass->getResultGraph();
graph.__debug_print(std::cout);
ASSERT_TRUE(graph.validate());
}
TEST(Effects, analysis_versions_3){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{0}= 3:: int.
a = x{0}:: int.
b = a :: int.
x{1} = b.
x{1}
}
)Code");
VersionsPass* pass = new VersionsPass(man);
pass->run();
VersionsGraph graph = pass->getResultGraph();
graph.__debug_print(std::cout);
ASSERT_TRUE(graph.validate());
std::cout << "========================\n";
graph.__debug_print(std::cout);
AttachmentsContainerDefault<std::list<Symbol>>* attachmentsDependency = graph.representAsAttachments();
CodeScope* scope = man->root->findFunction("test")->getEntryScope();
const std::list<Symbol>& dependenciesX1 = attachmentsDependency->get(Symbol{ScopedSymbol{1, 1}, scope});
ASSERT_EQ(3, dependenciesX1.size());
}
TEST(Effects, compilation_versions_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{1} = b.
b = a :: int.
a = x{0}:: int.
x{0}= 3:: int.
x{1}
}
)Code");
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::VersionsPass)){
VersionsPass* pass = new VersionsPass(man);
pass->run();
pass->finish();
}
int (*body)() = (int (*)())man->run();
int answer = body();
ASSERT_EQ(3, answer);
}
TEST(Effects, compilation_versions_versionInit1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{0} = 3.
x{0}
}
)Code");
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::VersionsPass)){
VersionsPass* pass = new VersionsPass(man);
pass->run();
pass->finish();
}
int (*body)() = (int (*)())man->run();
int answer = body();
ASSERT_EQ(3, answer);
}
TEST(Effects, compilation_versions_versionNext1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{0} = 5.
x{1} = x{0} - 2.
x{1}
}
)Code");
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::VersionsPass)){
VersionsPass* pass = new VersionsPass(man);
pass->run();
pass->finish();
}
int (*body)() = (int (*)())man->run();
int answer = body();
ASSERT_EQ(3, answer);
}
TEST(Effects, compilation_versions_IntrinsicCopy1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
test= function:: num; entry {
x{0} = 5.
b = intrinsic copy (x{0}).
x{1} = 2.
b - x{1}
}
)Code");
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::VersionsPass)){
VersionsPass* pass = new VersionsPass(man);
pass->run();
pass->finish();
}
int (*body)() = (int (*)())man->run();
int answer = body();
ASSERT_EQ(3, answer);
}
TEST(Effects, compilation_versions_varexchange){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
test= function:: num; entry {
a{0} = 3.
b{0} = 5.
tmp = intrinsic copy (a{0}).
a{1} = b{0}.
b{1} = tmp.
b{1}
}
)Code");
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::VersionsPass)){
VersionsPass* pass = new VersionsPass(man);
pass->run();
pass->finish();
}
int (*body)() = (int (*)())man->run();
int answer = body();
ASSERT_EQ(3, answer);
}
/*
TEST(Effects, analysis_versions_copy){
}
TEST(Effects, syntax_references1){
}
TEST(Effects, syntax_scope_versions1){
}
TEST(Effects, DynamicVersions_analysis){
}
*/
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
index 4aa5d7e..2057d42 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,106 +1,106 @@
#include "gtest/gtest.h"
-#include "passmanager.h"
-#include "Scanner.h"
-#include "Parser.h"
+#include "xreatemanager.h"
+#include "main/Scanner.h"
+#include "main/Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
TEST(InterfaceExternC, testAST) {
std::string code = " \
interface(extern-c){ \
xml2 = library:: pkgconfig(\"libxml-2.0\"). \
\
include { \
xml2 = [\"libxml/tree.h\"] \
}. \
} \
";
- Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
- Parser parser(&scanner);
+ xreate::grammar::main::Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
+ xreate::grammar::main::Parser parser(&scanner);
parser.Parse();
- ASSERT_EQ(1, parser.root.__externdata.size());
+ ASSERT_EQ(1, parser.root->__externdata.size());
- for (const ExternEntry& lib : parser.root.__externdata) {
+ for (const ExternEntry& lib : parser.root->__externdata) {
ASSERT_EQ("libxml-2.0", lib.package);
ASSERT_EQ(1, lib.headers.size());
ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
}
}
TEST(InterfaceExternC, testfetchPackageHeaders) {
ExternEntry entry{"libxml-2.0",
{}};
vector<string> args = ExternLayer::fetchPackageFlags(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
}
TEST(InterfaceExternC, testfetchPackageLibs) {
ExternEntry entry{"libxml-2.0",
{}};
vector<string> args = ExternLayer::fetchPackageLibs(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("xml2", args.at(0));
}
TEST(InterfaceExternC, testLoadLib) {
std::string msgErr;
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)) {
cout << msgErr;
ASSERT_EQ("", msgErr);
}
ASSERT_TRUE(true);
}
TEST(InterfaceExternC, testBSD1) {
std::string code = " \n\
interface(extern-c){ \n\
libbsd = library:: pkgconfig(\"libbsd\"). \n\
\n\
include { \n\
libbsd = [\"bsd/stdlib.h\"] \n\
}. \n\
} \n"
"main= function:: int; entry{arc4random_uniform(24) }";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t) entryPtr;
int answer = 24;
answer = entry();
cout << answer;
ASSERT_LT(answer, 24);
}
TEST(InterfaceExternC, testStructFields1) {
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r");
assert(input != nullptr);
- Scanner scanner(input);
- Parser parser(&scanner);
+ xreate::grammar::main::Scanner scanner(input);
+ xreate::grammar::main::Parser parser(&scanner);
parser.Parse();
- AST& ast = parser.root;
- CodeScope* body = ast.findFunction("test")->getEntryScope();
+ AST* ast = parser.root->finalize();
+ CodeScope* body = ast->findFunction("test")->getEntryScope();
const TypeAnnotation& tTree = body->getDeclaration(body->getSymbol("tree")).type;
- const ExpandedType& t2Tree = ast.expandType(tTree);
- LLVMLayer llvm(&ast);
+ const ExpandedType& t2Tree = ast->expandType(tTree);
+ LLVMLayer llvm(ast);
TypeUtils utils(&llvm);
std::vector<std::string>fields = utils.getStructFields(t2Tree);
auto field = std::find(fields.begin(), fields.end(), "children");
ASSERT_TRUE(field != fields.end());
}
diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp
index 21cdc9f..abb3606 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,381 +1,380 @@
#include "attachments.h"
using namespace xreate;
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "compilation/targetinterpretation.h"
#include "gtest/gtest.h"
#include "boost/scoped_ptr.hpp"
#define private public
-#include "Parser.h"
#include "pass/interpretationpass.h"
-using namespace xreate;
+using namespace xreate::grammar::main;
using namespace xreate::compilation;
TEST(Interpretation, Analysis_StatementIF_1){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
main = function::bool {
x = "a":: string.
y = if (x=="b"):: bool; interpretation(force) {
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, Compilation_StatementIF_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
main = function::int; entry {
x = "a":: string.
y = if (x=="b"):: string; interpretation(force) {
1
} else {
0
}.
y
}
)Code" );
- man->runWithoutCompilation();
+ 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, Analysis_StatementIF_InterpretCondition_1){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
main = function(x:: int):: int {
comm= "inc":: string; interpretation(force).
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, Compilation_StatementIF_InterpretCondition_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
main = function(x:: int):: int; entry {
comm= "inc":: string; interpretation(force).
y = if (comm == "inc")::int {x+1} else {x}.
y
}
)Code" );
- man->runWithoutCompilation();
+ 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, Compilation_StatementFOLD_INTERPRET_INPUT_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
main = function(x:: int):: int; entry {
commands = ["inc", "double", "dec"]:: [string]; interpretation(force).
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->runWithoutCompilation();
+ 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, StatementCall_RecursionNo_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
unwrap = function(data::undef, keys::undef):: undef; interpretation(force){
loop fold(keys->key::string, data->a):: undef {
a[key]
}
}
start = function::num; entry{
result = unwrap(
{
a = {
b =
{
c = "core"
}
}
}, ["a", "b", "c"])::undef.
result == "core"
}
)Code" );
- man->runWithoutCompilation();
+ 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(1, result);
}
TEST(Interpretation, StatementCall_RecursionDirect_1){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
unwrap = function(data:: X):: Y {
if (data[0] == "a")::Y {0} else {unwrap(data[0])}
}
entry = function:: i8; entry {
unwrap([[[["a"]]]]):: i8; interpretation(force)
}
)Code" );
- man->runWithoutCompilation();
+ 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);
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, StatementCall_RecursionIndirect_1){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
funcA = function(data:: X):: Y {
if (data == "a")::Y {0} else {funcB(data)}
}
funcB = function(data:: X):: Y {
if (data == "b")::Y {1} else {funcA(data)}
}
entry = function:: i8; entry {
funcA(""):: i8; interpretation(force)
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
ASSERT_DEATH(pass->run(), "Indirect recursion detected");
}
TEST(Interpretation, PartialIntr_1){
- PassManager* man = PassManager::prepareForCode(
+ XreateManager* man = XreateManager::prepare(
R"Code(
evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
switch(code)::int
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
}
main = function::int; entry {
commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
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, 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, Compilation_PartialIntr_2){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
switch(code)::int
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
case default {argument}
}
main = function::int; entry {
commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code" );
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::InterpretationPass)){
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(21, result);
}
TEST(Interpretation, PartialIntr_3){
- PassManager* man = PassManager::prepareForCode(
+ details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(
R"Code(
Command= type variant (INC, DEC, DOUBLE).
evaluate= function(argument:: num, code:: Command; interpretation(force)):: num {
switch(code)::int
case (INC) {argument + 1}
case (DEC) {argument - 1}
case (DOUBLE) {argument * 2}
case default {argument}
}
main = function::int; entry {
commands= [INC, DOUBLE, DEC]:: [Command]; interpretation(force).
loop fold(commands->comm::Command, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code" );
- man->runWithoutCompilation();
+ man->analyse();
if (!man->isPassRegistered(PassId::InterpretationPass)){
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(21, result);
}
TEST(InterpretationExamples, Regexp1){
FILE* input = fopen("scripts/dsl/regexp.xreate","r");
assert(input != nullptr);
- std::unique_ptr<PassManager> man(PassManager::prepareForCode(input));
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(4, result);
}
//TOTEST call indirect recursion(w/o tags)
//TASk implement and test Loop Inf (fix acc types in coco grammar)
diff --git a/cpp/tests/loops.cpp b/cpp/tests/loops.cpp
index be08250..6947ae6 100644
--- a/cpp/tests/loops.cpp
+++ b/cpp/tests/loops.cpp
@@ -1,178 +1,178 @@
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "gtest/gtest.h"
using namespace std;
TEST(Loop, SimpleLoop1){
string code =
R"CODE(
main = function:: int; entry {
input = [1..5]:: [int].
loop fold(input->el::int, 0->sum)::int
{
sum + el
}
}
)CODE";
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(15, answerActual);
}
TEST(Loop, Break1){
string code =
R"CODE(
main = function:: int; entry {
input = [1..10]:: [int].
loop fold(input->el::int, 0->sum)::int
{
if (sum>5)::int {
sum:: int; break
} else {sum+el}
}
}
)CODE";
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(6, answerActual);
}
TEST(Loop, NestedLoopsSimple1){
string code =
R"CODE(
main = function:: int; entry {
listX = [1..5]:: [int].
loop fold(listX->x::int, 0->acc)::int
{
listY = [1..5]:: [int].
row = loop fold(listY->y::int, 1->acc):: int {
acc * ( y + x)
}.
acc + row
}
}
)CODE";
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(55320, answerActual);
}
TEST(Loop, NestedLoopsBreak1){
string code =
R"CODE(
main = function:: int; entry {
listX = [1..5]:: [int].
loop fold(listX->x::int, 0->acc)::int
{
listY = [1..5]:: [int].
row = loop fold(listY->y::int, 1->acc):: int {
res = acc * ( y + x) :: int.
if (res > 20):: int {
20:: int; break
} else {
res
}
}.
acc + row
}
}
)CODE";
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(100, answerActual);
}
TEST(Loop, NestedLoopsBreak2){
string code =
R"CODE(
main = function:: int; entry {
listX = [1..3]:: [int].
loop fold(listX->x::int, 0->acc)::int
{
listY = [1..5]:: [int].
row = loop fold(listY->y::int, 1->acc):: int {
res = acc * y :: int.
if (res > 24):: int {
24:: int; break
} else {
res
}
}.
if (x==3)::int{
acc:: int; break
} else {
acc + row
}
}
}
)CODE";
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(48, answerActual);
}
//TEST nested loop breaks.
//TEST 2 breaks^ outer loop break, inner loop break
TEST(Loop, InfiniteLoop1){
string code =
R"Code(
fac = function(x:: int):: int{
range = [2..x] :: [int].
loop fold(range->i::int, 1->acc)::int {
acc * i
}
}
main = function:: int; entry {
loop fold inf(2->state) :: int {
if (fac(state)==120)::int {
state::int; break
} else {state + 1}
}
}
)Code" ;
- xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ xreate::XreateManager* man = xreate::XreateManager::prepare(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
ASSERT_EQ(5, answerActual);
}
\ No newline at end of file
diff --git a/cpp/tests/main.cpp b/cpp/tests/main.cpp
index 2385205..0e1f7de 100644
--- a/cpp/tests/main.cpp
+++ b/cpp/tests/main.cpp
@@ -1,15 +1,14 @@
#include "utils.h"
#include <gtest/gtest.h>
using namespace std;
using namespace xreate;
-int main(int argc, char **argv) {
- testing::GTEST_FLAG(color) = "yes";
+int main(int argc, char **argv) { testing::GTEST_FLAG(color) = "yes";
string testsTemplate = Config::get("tests.template");
string testsFilter = Config::get(string("tests.templates.") + testsTemplate);
testing::GTEST_FLAG(filter) = testsFilter;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/cpp/tests/modules.cpp b/cpp/tests/modules.cpp
new file mode 100644
index 0000000..10c1ead
--- /dev/null
+++ b/cpp/tests/modules.cpp
@@ -0,0 +1,271 @@
+/*
+ * modules.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on June 18, 2017, 8:25 PM
+ */
+
+class Modules_AST2_Test;
+class Modules_Discovery1_Test;
+class Modules_Solve1_Test;
+
+#define FRIENDS_MODULES_TESTS \
+ friend class ::Modules_AST2_Test; \
+ friend class ::Modules_Discovery1_Test; \
+ friend class ::Modules_Solve1_Test;
+
+#include "modules.h"
+#include "misc/xreatemanager-decorators.h"
+#include "misc/xreatemanager-modules.h"
+#include "xreatemanager.h"
+#include "modules/Parser.h"
+#include "gtest/gtest.h"
+#include <boost/filesystem.hpp>
+#include <regex>
+#include <clingo/clingocontrol.hh>
+
+namespace fs = boost::filesystem;
+
+using namespace std;
+using namespace xreate::grammar::modules;
+
+TEST(Modules, AST1) {
+ FILE* input = fopen("scripts/dsl/regexp.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+ ASSERT_EQ(parser.errors->count, 0);
+}
+
+TEST(Modules, AST2){
+ string code = R"Code(
+ module {
+ name(test1).
+ status(untested).
+
+ require provides(logging).
+ include controller("/tmp/test-controller.ls").
+ discover("/tmp/root/").
+ }
+ )Code";
+
+ Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
+ Parser parser(&scanner);
+ parser.Parse();
+
+ xreate::ModuleRecord module = parser.module;
+
+ ASSERT_EQ(2, module.__properties.size());
+ ASSERT_EQ("name", module.__properties.front().getValueString());
+ ASSERT_EQ("status", module.__properties.back().getValueString());
+
+ ASSERT_EQ(1, module.__queries.size());
+ ASSERT_EQ("provides", module.__queries.front().getValueString());
+
+ ASSERT_EQ(1, module.__controllers.size());
+ ASSERT_EQ("/tmp/test-controller.ls", module.__controllers.front());
+
+ ASSERT_EQ(1, module.__discoveries.size());
+ ASSERT_EQ("/tmp/root/", module.__discoveries.front());
+}
+
+TEST(Modules, Discovery1){
+ const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54723/";
+
+ string codeA =
+R"Code(module {
+ name(testA).
+ status(needToTestMore).
+})Code";
+
+ string codeB =
+R"Code(module {
+ name(testB).
+ status(needToTestEvenMore).
+})Code";
+
+ string codeMain = string("module{discover \"") + dirModulesRoot + "\".}";
+
+ fs::create_directories(dirModulesRoot);
+ fs::ofstream fileA(dirModulesRoot + "a.xreate");
+ fileA << codeA;
+ fileA.close();
+
+ fs::ofstream fileB(dirModulesRoot + "b.xreate");
+ fileB << codeB;
+ fileB.close();
+
+ Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
+ Parser parser(&scanner);
+ parser.Parse();
+
+ xreate::ModulesRegistry registry;
+ xreate::ModulesSolver solver(&registry);
+ solver.discoverModules(parser.module);
+ fs::remove_all(dirModulesRoot);
+
+ std::string output = solver.__program.str();
+ cout << output << endl;
+ ASSERT_NE(string::npos, output.find("bind_module(0, name(testA))."));
+ ASSERT_NE(string::npos, output.find("bind_module(1, status(needToTestEvenMore))."));
+}
+
+TEST(Modules, Requests1){
+
+}
+
+TEST(Modules, Solve1){
+ const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54724/";
+
+ string codeA =
+R"Code(module {
+ name(testA).
+ provide(superService).
+ status(needToTestMore).
+})Code";
+
+ string codeB =
+R"Code(module {
+ name(testB).
+ provide(superService).
+ status(needToTestEvenMore).
+})Code";
+
+ string codeMain =
+R"Code(module {
+ discover("/tmp/testModulesDiscovery1_t54724/")
+ include controller ("/tmp/testModulesDiscovery1_t54724/controller")
+
+ require (superService)
+})Code";
+
+ string codeController =
+R"Code(
+status_score(0, needToTestEvenMore).
+status_score(1, needToTestMore).
+
+module_include_candidate(X, Y, Request):-
+ module_require(X, Request); bind_module(Y, provide(Request)).
+
+module_include_winner(X, Request, MaxScore) :-
+ MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)};
+ module_require(X, Request).
+
+module_include(X, Y) :-
+ module_include_winner(X, Request, MaxScore);
+ bind_module(Y, provide(Request));
+ bind_module(Y, status(Status));
+ status_score(MaxScore, Status).
+)Code";
+
+ fs::create_directories(dirModulesRoot);
+ fs::ofstream fileA(dirModulesRoot + "a.xreate");
+ fileA << codeA;
+ fileA.close();
+
+ fs::ofstream fileB(dirModulesRoot + "b.xreate");
+ fileB << codeB;
+ fileB.close();
+
+ fs::ofstream fileController(dirModulesRoot + "controller");
+ fileController << codeController;
+ fileController.close();
+
+ Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
+ Parser parser(&scanner);
+ parser.Parse();
+
+ xreate::ModulesRegistry registry;
+ xreate::ModulesSolver solver(&registry);
+ solver.init("", parser.module);
+ fs::remove_all(dirModulesRoot);
+
+ cout << solver.__program.str() << endl;
+ std::list<std::string> modulesRequired = solver.run(parser.module);
+
+ ASSERT_EQ(1, modulesRequired.size());
+ string moduleActualRequired = modulesRequired.front();
+
+ string moduleExpected = dirModulesRoot + "a.xreate";
+ ASSERT_EQ(moduleExpected, moduleActualRequired);
+}
+
+TEST(Modules, Compilation1){
+ const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54725/";
+
+ string codeMain =
+R"Code(
+module {
+ discover("/tmp/testModulesDiscovery1_t54725/")
+ include controller("/tmp/testModulesDiscovery1_t54725/controller")
+
+ require (superService)
+}
+
+test = function:: int; entry {
+ getYourNumber()
+}
+)Code";
+
+ string codeA =
+R"Code(module {
+ name(testA).
+ provide(superService).
+ status(needToTestEvenMore).
+}
+
+getYourNumber= function:: int {0}
+)Code";
+
+ string codeB =
+R"Code(module {
+ name(testB).
+ provide(superService).
+ status(needToTestMore).
+}
+
+getYourNumber= function:: int {1}
+)Code";
+
+string codeController =
+R"Code(
+status_score(0, needToTestEvenMore).
+status_score(1, needToTestMore).
+
+module_include_candidate(X, Y, Request):-
+ module_require(X, Request); bind_module(Y, provide(Request)).
+
+module_include_winner(X, Request, MaxScore) :-
+ MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)};
+ module_require(X, Request).
+
+module_include(X, Y) :-
+ module_include_winner(X, Request, MaxScore);
+ bind_module(Y, provide(Request));
+ bind_module(Y, status(Status));
+ status_score(MaxScore, Status).
+)Code";
+
+ fs::create_directories(dirModulesRoot);
+ fs::ofstream fileA(dirModulesRoot + "a.xreate");
+ fileA << codeA;
+ fileA.close();
+
+ fs::ofstream fileB(dirModulesRoot + "b.xreate");
+ fileB << codeB;
+ fileB.close();
+
+ fs::ofstream fileController(dirModulesRoot + "controller");
+ fileController << codeController;
+ fileController.close();
+
+ auto man = new XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
+ man->prepareCode(std::move(codeMain));
+ fs::remove_all(dirModulesRoot);
+
+ int (*funcMain)() = (int (*)()) man->run();
+ int result = funcMain();
+ ASSERT_EQ(1, result);
+}
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 5ff99b6..30ea9a0 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,163 +1,164 @@
/*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
-#include "passmanager.h"
+#include "xreatemanager.h"
#include "llvmlayer.h"
-#include "Parser.h"
+#include "main/Parser.h"
using namespace std;
-using namespace xreate;
+using namespace xreate::grammar::main;
TEST(Types, DependantTypes1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeXmlNode = program->root->findType("XmlNode");
ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator);
ASSERT_EQ(2, typeXmlNode->__operands.size());
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value);
}
TEST(Types, DependantTypes2) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Template = type Template(Leaf) [Leaf, [Leaf[content]]]."
"Concrete = type alias Template(XmlNode).";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
}
TEST(Types, TreeType1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
auto typeLink = typeConcrete->__operands.at(1).__operands.at(0);
ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId);
}
TEST(Types, TreeType1LLvm){
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
TEST(Types, ArrayOfExternal1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
+
parser.Parse();
+ AST* ast = parser.root->finalize();
- AST& ast = parser.root;
- CodeScope* body = ast.findFunction("test")->getEntryScope();
+ CodeScope* body = ast->findFunction("test")->getEntryScope();
const TypeAnnotation& t = body->getDeclaration(body->getSymbol("childrenRaw")).type;
- const ExpandedType& t2 = ast.expandType(t);
+ const ExpandedType& t2 = ast->expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
}
TEST(Types, ExternType1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
- AST& ast = parser.root;
- CodeScope* body = ast.findFunction("test")->getEntryScope();
+ AST* ast = parser.root->finalize();
+ CodeScope* body = ast->findFunction("test")->getEntryScope();
const TypeAnnotation& t = body->getDeclaration(body->getSymbol("tree")).type;
- const ExpandedType& t2 = ast.expandType(t);
+ const ExpandedType& t2 = ast->expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
}
TEST(Types, ast_VariantType1){
string&& code =
" colors = type variant (RED, BLUE, GREEN).\n"
" test = function:: colors; entry {GREEN}";
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
ExpandedType typ = program->root->findType("colors");
EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody();
EXPECT_EQ(Expression::VARIANT, eRed.__state);
const ExpandedType& typ2 = program->root->expandType(eRed.type);
EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
program->run();
}
TEST(Types, full_VariantType_Switch1){
string&& code =
" colors = type variant (RED, BLUE, GREEN). \n"
" test = function:: colors {GREEN} \n"
"main = function:: int; entry { \n"
" switch(test()):: int \n"
" case (GREEN) {0} \n"
" case default {1} \n"
"}";
- PassManager* man = PassManager::prepareForCode(move(code));
+ XreateManager* man = XreateManager::prepare(move(code));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(0, main());
}
//TOTEST string type
diff --git a/grammar/gen-grammar b/grammar/gen-grammar
new file mode 100755
index 0000000..237f5b5
--- /dev/null
+++ b/grammar/gen-grammar
@@ -0,0 +1,9 @@
+COCO_EXECUTABLE=${2:-cococpp}
+COCO_FRAMES_PATH=${3:-/usr/share/coco-cpp/}
+
+echo "Run coco generator: "
+
+case $1 in
+ main) $COCO_EXECUTABLE ./xreate.ATG -frames $COCO_FRAMES_PATH -o main -namespace xreate::grammar::main;;
+ modules) $COCO_EXECUTABLE ./modules.ATG -frames $COCO_FRAMES_PATH -o modules -namespace xreate::grammar::modules;;
+esac
diff --git a/grammar/modules.ATG b/grammar/modules.ATG
new file mode 100644
index 0000000..43aaacf
--- /dev/null
+++ b/grammar/modules.ATG
@@ -0,0 +1,96 @@
+#include "modules.h"
+
+COMPILER Modules
+
+ModuleRecord module;
+
+int nextToken()
+{
+ scanner->ResetPeek();
+ return scanner->Peek()->kind;
+}
+
+bool checkParametersList()
+{
+ return la->kind == _ident && nextToken() == _lparen;
+}
+
+CHARACTERS
+ letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
+ digit = "0123456789".
+ any = ANY - '"'.
+ cr = '\r'.
+ lf = '\n'.
+ tab = '\t'.
+
+
+TOKENS
+ string = '"' { any } '"'.
+ ident = (letter | '_') {letter | digit | '_'}.
+ lparen = '('.
+
+
+COMMENTS FROM "/*" TO "*/" NESTED
+COMMENTS FROM "//" TO lf
+
+IGNORE cr + lf + tab
+
+PRODUCTIONS
+
+Block =
+'{'
+ { string
+ | Block
+ | ANY
+ }
+'}'.
+
+Modules =
+{
+ ModulesInterface
+ | SkipXreateOperators
+}.
+
+ModulesInterface = "module" '{'
+ {ModulesStatement}
+'}'.
+
+ModulesStatement = (. std::wstring path; Expression query; .)
+( "require" '(' MetaSimpExpr<query> ')' '.' (. module.addModuleQuery(query); .)
+
+ | "include" "controller" '(' string (. module.addControllerPath(Atom<String_t>(t->val).get()); .)
+ ')' '.'
+ | "discover" '(' string (. module.addDiscoveryPath(Atom<String_t>(t->val).get()); .)
+ ')' '.'
+ | MetaSimpExpr<query> '.' (. module.addProperty(query); .)
+).
+
+MetaSimpExpr<Expression& e>= (. Expression e2; .)
+( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
+| IF(checkParametersList()) ident (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(t->val))}); .)
+ '(' [ MetaCalleeParams<e> ] ')'
+| ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
+).
+
+MetaCalleeParams<Expression& e> = (. Expression e2; .)
+ MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
+ {',' MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
+ }.
+
+
+
+SkipXreateOperators =
+{ "rule" {ANY} Block
+ | "interface" {ANY} Block
+ | "import" {ANY} '.'
+ | "case" "context" {ANY} Block
+ | {ANY} '='
+ (
+ "function" {ANY} Block
+ | "type" {ANY} '.'
+ )
+}.
+
+
+
+END Modules.
diff --git a/coco/xreate.ATG b/grammar/xreate.ATG
similarity index 93%
rename from coco/xreate.ATG
rename to grammar/xreate.ATG
index 66e8ad4..ac15f56 100644
--- a/coco/xreate.ATG
+++ b/grammar/xreate.ATG
@@ -1,600 +1,607 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
#include <string>
#include <stack>
#define wprintf(format, ...) \
char __buffer[100]; \
wcstombs(__buffer, format, 100); \
fprintf(stderr, __buffer, __VA_ARGS__)
using namespace xreate;
using namespace std;
COMPILER Xreate
- xreate::AST root; // current program unit
+ xreate::details::incomplete::AST* root = nullptr; // current program unit
+
+ void ensureInitalizedAST(){
+ if (root == nullptr) root = new xreate::details::incomplete::AST();
+ }
struct {
std::stack<xreate::CodeScope*> scopesOld;
xreate::CodeScope* scope = nullptr;
} context;
void pushContextScope(CodeScope* scope){
context.scopesOld.push(context.scope);
context.scope = scope;
}
void popContextScope(){
context.scope = context.scopesOld.top();
context.scopesOld.pop();
}
int nextToken()
{
scanner->ResetPeek();
return scanner->Peek()->kind;
}
bool checkParametersList()
{
return la->kind == _ident && nextToken() == _lparen;
}
bool checkInfix()
{
return la->kind == _ident && nextToken() == _ident;
}
bool checkIndex()
{
return la->kind == _ident && nextToken() == _lbrack;
}
bool checkFuncDecl()
{
if (la->kind != _ident) return false;
int token2 = nextToken();
int token3 = scanner->Peek()->kind;
return token2 == _assign && (token3 == _function || token3 == _pre);
}
bool checkAssignment()
{
if (la->kind != _ident) return false;
scanner->ResetPeek();
int token2 = scanner->Peek()->kind;
if (token2 == _lcurbrack) {
scanner->Peek();
int token3 = scanner->Peek()->kind;
if (token3 != _rcurbrack) return false;
int token4 = scanner->Peek()->kind;
return token4 == _assign;
}
return token2 == _assign;
}
void recognizeIdentifier(Expression& i){
if (!context.scope->recognizeIdentifier(i)){
- if (!root.recognizeVariantIdentifier(i)){
- root.postponeIdentifier(context.scope, i);
+ if (!root->recognizeVariantIdentifier(i)){
+ root->postponeIdentifier(context.scope, i);
}
}
}
enum SwitchKind{SWITCH_NORMAL, SWITCH_META};
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
ident = (letter | '_') {letter | digit | '_'}.
number = (digit | '-' digit) {digit}.
string = '"' { any } '"'.
function = "function".
pre = "pre".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
lcurbrack = '{'.
rcurbrack = '}'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
context = "context".
tagcolon = "::".
lse = "<=".
lss = "<".
gte = ">=".
gtr = ">".
ne1 = "!=".
ne2= "<>".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
-Xreate = (. Function* function; .)
+Xreate = (. Function* function; ensureInitalizedAST(); .)
{( RuleDecl
| InterfaceData | Imprt | ContextSection
- | IF(checkFuncDecl()) FDecl<function> (. root.add(function); .)
+ | IF(checkFuncDecl()) FDecl<function> (. root->add(function); .)
| TDecl
-)} (. root.recognizePostponedIdentifiers(); .)
+ | SkipModulesSection
+)} (. .)
.
Ident<std::wstring& name>
= ident (. name = t->val; .).
VarIdent<Expression& e>
= ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
[ lcurbrack (
ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .)
| number (. Attachments::put<VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
) rcurbrack ] .
FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .)
Ident<fname> assign
[pre (. flagIsPrefunct = true; .)]
function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .)
['(' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
{',' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom <Identifier_t>(argName), move(binding));.)
} ')']
[ tagcolon
( IF(flagIsPrefunct) FnTag<f>
| Type<typOut>
)
{';' FnTag<f> }]
BDecl<entry> (. entry->getBody().bindType(move(typOut));.)
.
ContextSection<>= (. Expression context; Function* f; .)
"case" "context" tagcolon MetaSimpExpr<context>
-lcurbrack { FDecl<f> (. f->guardContext = context; root.add(f); .)
+lcurbrack { FDecl<f> (. f->guardContext = context; root->add(f); .)
} rcurbrack.
/**
* TYPES
*
*/
TypeTerm<TypePrimitive& typ> = (. std::wstring tid; .)
("string" (. typ = TypePrimitive::String;.)
| "num" (. typ = TypePrimitive::Num;.)
| "int" (. typ = TypePrimitive::Int;.)
| "float" (. typ = TypePrimitive::Float;.)
| "bool" (. typ = TypePrimitive::Bool; .)
| "i8" (. typ = TypePrimitive::I8; .)
| "i32" (. typ = TypePrimitive::I32; .)
| "i64" (. typ = TypePrimitive::I64; .)
).
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
| TypeTerm<typ3> (. typ = typ3; .)
| IF (checkIndex()) Ident<tid> lbrack
Ident<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> (. typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
} rbrack
| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
['(' Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
{',' Type<typ2> (. typ.__operands.push_back(typ2); .)
} ')']
) .
TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
'[' Type<ty> (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .)
{',' Type<ty> (. typ.__operator = TypeOperator::TUPLE; typ.__operands.push_back(ty); .)
}']'
.
TStruct<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring field; .)
lcurbrack
Ident<field> tagcolon Type<t> (. typ = TypeAnnotation(TypeOperator::STRUCT, {t}); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> tagcolon Type<t>} (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
rcurbrack.
TDecl = (. std::wstring ttag; TypeAnnotation t, t1; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
Ident<tname> assign "type"
(
- "alias" Type<t> (. root.add(move(t), Atom<Identifier_t>(tname)); .)
+ "alias" Type<t> (. root->add(move(t), Atom<Identifier_t>(tname)); .)
| "variant" lparen Ident<arg> (. t = TypeAnnotation(TypeOperator::VARIANT, {}); args.push_back(Atom<Identifier_t>(arg)); .)
{',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
- } rparen (. t.addFields(move(args)); root.add(move(t), Atom<Identifier_t>(tname)); .)
+ } rparen (. t.addFields(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
| Ident<ttag>
['(' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
{',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
} ')']
- Type<t> (. t.addBindings(move(args)); root.add(move(t), Atom<Identifier_t>(tname)); .)
+ Type<t> (. t.addBindings(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
) '.'
.
ContextDecl<CodeScope * scope> = (. Expression tag; .)
context tagcolon
MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
VDecl<CodeScope* f> = (. std::wstring vname; Expression var, value;.)
VarIdent<var> assign ExprTyped<value> (. f->addDeclaration(move(var), move(value)); .)
.
//TODO forbid multiple body declaration (ExprTyped)
BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); .)
{(IF(checkAssignment()) VDecl<scope> '.'
| RuleContextDecl<scope>
| ContextDecl<scope>'.'
| ExprTyped<body> (. scope->setBody(body); .)
)} (. popContextScope(); .)
rcurbrack .
-IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(context.scope)); .)
+IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root->add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new xreate::CodeScope(context.scope)); .)
"if" '(' Expr<cond> ')' (. e = Expression(Operator::IF, {cond}); .)
tagcolon ExprAnnotations<e>
BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e> =
(. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl;
- ManagedScpPtr block = root.add(new xreate::CodeScope(context.scope)); .)
+ ManagedScpPtr block = root->add(new xreate::CodeScope(context.scope)); .)
"loop"
("map" '(' Expr<eIn> implic Ident<varEl> (. e = Expression(Operator::MAP, {eIn}); .)
tagcolon ExprAnnotations<tagsEl> ')' tagcolon ExprAnnotations<e> BDecl<&*block>
(.
e.addBindings({Atom<Identifier_t>(varEl)});
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
e.addBlock(block);
.)
|"fold"
("inf" '(' Expr<eAcc> implic Ident<varAcc> ')'
(.
e = Expression(Operator::FOLD_INF, {eAcc});
e.addBindings({Atom<Identifier_t>(varAcc)});
.)
tagcolon ExprAnnotations<e> BDecl<&*block>
(.
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
e.addBlock(block);
.)
| '(' Expr<eIn> implic Ident<varEl> tagcolon ExprAnnotations<tagsEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc>')'
(.
e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
.)
tagcolon ExprAnnotations<e> BDecl<&*block>
(.
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
e.addBlock(block);
.)
)
| "context" '(' string (. contextClass = t->val; .)
')' BDecl<&*block>
(. e = Expression(Operator::LOOP_CONTEXT, {Expression(Atom<String_t>(std::move(contextClass)))});
e.addBlock(block);
.)
).
SwitchDecl<Expression& eSwitch, SwitchKind flagSwitchKind> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.)
["switch"
( "ad" "hoc" lparen Expr<eCondition> tagcolon MetaSimpExpr<tag> rparen (. eSwitch.op = Operator::SWITCH_ADHOC;
eSwitch.operands.push_back(eCondition);
eSwitch.addTags({tag});
flagSwitchKind = SWITCH_META; .)
| lparen Expr<eCondition> rparen tagcolon ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
)
]
CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
.
-CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); Expression condition; .)
+CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root->add(new xreate::CodeScope(context.scope)); Expression condition; .)
"case"
( IF(flagSwitchKind == SWITCH_META)
lparen MetaSimpExpr<condition> rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.)
| "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
exprCase.addBlock(scope);
outer.operands.insert(++outer.operands.begin(), exprCase); .)
- | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
+ | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new xreate::CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .)
).
CaseParams<CodeScope* scope> = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
{',' ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
} (. scope->setBody(guard); popContextScope(); .)
.
IntrinsicDecl<Expression& outer>= (. std::wstring name; .)
"intrinsic" Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom<Identifier_t>(name)); .)
lparen [CalleeParams<outer>] rparen .
/*============================ INTERFACES ===============================*/
Imprt<> =
-"import" "raw" lparen string (. root.__rawImports.push_back(Atom<String_t>(t->val).get()); .)
-rparen .
+"import" "raw" lparen string (. root->__rawImports.push_back(Atom<String_t>(t->val).get()); .)
+rparen '.'.
InterfaceData<> = "interface" '('
( "dfa" ')' InterfaceDFA
| "extern-c" ')' InterfaceExternC
| "cfa" ')' InterfaceCFA
| "adhoc" ')' InterfaceAdhoc
).
InterfaceAdhoc<> =
'{' { PrefunctionSchemeDecl } '}'.
PrefunctionSchemeDecl<> = (. TypeAnnotation typReturn; std::wstring prefName; Expression exprCases; .)
pre function Ident<prefName> tagcolon Type<typReturn>
lcurbrack SwitchDecl<exprCases, SWITCH_META> rcurbrack
(. Expression prefData(Operator::CALL, {Atom<Identifier_t>(prefName), exprCases});
prefData.bindType(typReturn);
- root.addInterfaceData(Adhoc, move(prefData));
+ root->addInterfaceData(Adhoc, move(prefData));
.).
InterfaceExternC<> = (.xreate::ExternData data; .)
'{' {IncludeExternDecl<data> | LibExternDecl<data> } '}'
- (. root.addExternData(move(data)); .)
+ (. root->addExternData(move(data)); .)
.
LibExternDecl<xreate::ExternData& data> = (. std::wstring pkgname, libname; .)
Ident<libname> assign "library" tagcolon "pkgconfig"
'(' string (. pkgname = t->val; .)
')' '.' (. data.addLibrary(Atom<Identifier_t>(libname), Atom<String_t>(pkgname)); .)
.
IncludeExternDecl<xreate::ExternData& data> = (. Expression inc; .)
"include" StructLiteral<inc> '.' (. data.addIncludeDecl(move(inc)); .)
.
InterfaceDFA<> = '{' { InstructDecl } '}' .
InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
"operator" InstructAlias<op> tagcolon '(' (.scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] ')' [ implic MetaSimpExpr<tag> (. tags[0] = tag; .)
- ] (. root.addDFAData(move(scheme)); .)
+ ] (. root->addDFAData(move(scheme)); .)
'.'.
InstructAlias<Operator& op> =
(
"map" (. op = Operator::MAP; .)
| "list_range" (. op = Operator::LIST_RANGE; .)
| "list" (. op = Operator::LIST; .)
| "fold" (. op = Operator::FOLD; .)
| "index" (. op = Operator::INDEX; .)
).
InterfaceCFA<> = '{' { InstructCFADecl } '}' .
InstructCFADecl<> = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands; .)
"operator" InstructAlias<op> tagcolon (. scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
-] '.' (. root.addInterfaceData(CFA, move(scheme)); .).
+] '.' (. root->addInterfaceData(CFA, move(scheme)); .).
/*============================ METAPROGRAMMING ===============================*/
// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
// }.
FnTag<Function* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
MetaSimpExpr<tag>
['-' TagMod<mod>] (. f->addTag(std::move(tag), mod); .).
TagMod<TagModifier& mod> =
( "assert" (. mod = TagModifier::ASSERT; .)
| "require" (. mod = TagModifier::REQUIRE; .)
).
RuleDecl<> =
"rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
'(' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
{',' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
} ')'
["case" RGuard<guards> {',' RGuard<guards>}]
'{' RBody<args, guards> '}' .
/* - TODO use RGuard for guards-*/
RuleContextDecl<CodeScope* scope> = (.Expression eHead, eGuards, eBody; .)
"rule" "context" tagcolon MetaSimpExpr<eHead>
"case" lparen MetaSimpExpr<eGuards> rparen
'{' MetaSimpExpr<eBody> '}' (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .).
Domain<DomainAnnotation& dom> =
(
"function" (. dom = DomainAnnotation::FUNCTION; .)
| "variable" (. dom = DomainAnnotation::VARIABLE; .)
).
RGuard<RuleGuards& guards>= (. Expression e; .)
MetaExpr<e> (. guards.add(std::move(e)); .).
MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
MetaExpr2<e>
[MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
].
MetaExpr2<Expression& e>=
(
'(' MetaExpr<e> ')'
| MetaSimpExpr<e>
).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
'(' [ MetaCalleeParams<e> ] ')'
| IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
(. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
e.addArg(Expression(Atom<Identifier_t>(i1)));
e.addArg(std::move(e2));
.)
| Ident<i1> (. e = Expression(Atom<Identifier_t>(i1)); .)
).
MetaCalleeParams<Expression& e> = (. Expression e2; .)
MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
{',' MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
}.
RBody<const RuleArguments& args, const RuleGuards& guards> =
(. Expression e; std::wstring msg; .)
"warning" MetaExpr<e> ["message" string (. msg = t->val; .)
-] (. root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
+] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
.
MetaOp< Operator& op> =
implic (. op = Operator::IMPL; .)
.
/*============================ Expressions ===============================*/
ExprAnnotations<Expression& e> = (. TypeAnnotation typ; std::list<Expression> tags; Expression tag; e.tags.clear();.)
Type<typ> (. e.bindType(move(typ)); .)
{';' MetaSimpExpr<tag> (. tags.push_back(tag); .)
} (. e.addTags(tags); .)
.
ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
Expr< Expression& e> (. Operator op; Expression e2; .)
= ExprArithmAdd<e>
[ RelOp<op>
ExprArithmAdd<e2> (. e = Expression(op, {e, e2}); .)
].
ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .)
ExprArithmMul< e>
[ AddOp< op>
ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
].
ExprArithmMul< Expression& e> (. Operator op; Expression e2; .)
= ExprPostfix< e>
[ MulOp< op>
ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .)
].
ExprPostfix<Expression& e>
= Term<e>
[lbrack (. e = Expression(Operator::INDEX, {e}); .)
CalleeParams<e> rbrack
].
Term< Expression& e> (. std::wstring name; e = Expression(); .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); .)
'(' [CalleeParams<e>] ')'
| VarIdent<e> (. recognizeIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
| LoopDecl<e>
| IfDecl<e>
| SwitchDecl<e, SWITCH_NORMAL>
| AdhocDecl<e>
| IntrinsicDecl<e>
| "true" (. e = Expression(Atom<Number_t>(1)); e.bindType(TypePrimitive::Bool); .)
| "false" (. e = Expression(Atom<Number_t>(0)); e.bindType(TypePrimitive::Bool); .)
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
| '-' Term<e> (. e = Expression(Operator::NEG, {e}); .)
| '(' ExprTyped<e> ')'
).
StructLiteral<Expression& e> = (. std::wstring key; Expression val; std::list<Atom<Identifier_t>> keys; .)
'{' Ident<key> '=' Expr<val> (. keys.push_back(Atom<Identifier_t>(key)); e = Expression(Operator::LIST_NAMED, {val}); .)
{',' Ident<key> '=' Expr<val> (.e.addArg(Expression(val)); keys.push_back(Atom<Identifier_t>(key)); .)
} '}' (. e.addBindings(keys.begin(), keys.end()); .)
.
ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
'['
[ Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
(".." Expr<eTo> (. e.addArg(Expression(eTo)); e.setOp(Operator::LIST_RANGE); .)
|{',' Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
} (. e.setOp(Operator::LIST); .)
) ] ']'.
AdhocDecl<Expression& e> = (. Expression command; .)
"ad" "hoc" MetaSimpExpr<command> (. AdhocExpression exprAdhoc; exprAdhoc.setCommand(command); e = exprAdhoc; .).
CalleeParams<Expression& e> = (. Expression e2; .)
ExprTyped<e2> (. e.addArg(Expression(e2)); .)
{',' ExprTyped<e2> (. e.addArg(Expression(e2)); .)
}.
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| (ne1 | ne2) (. op = Operator::NE; .)
| lse (. op = Operator::LSE; .)
| lss (. op = Operator::LSS; .)
| gte (. op = Operator::GTE; .)
| gtr (. op = Operator::GTR; .)
).
+SkipModulesSection = "module" '{' {ANY} '}'.
+
END Xreate.
diff --git a/scripts/containers/Containers_Implementation_LinkedList1.xreate b/scripts/containers/Containers_Implementation_LinkedList1.xreate
index a645574..c1998de 100644
--- a/scripts/containers/Containers_Implementation_LinkedList1.xreate
+++ b/scripts/containers/Containers_Implementation_LinkedList1.xreate
@@ -1,47 +1,47 @@
// EXTERN INCLUDES
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["libxml/tree.h"]
}.
}
// CONTAINERS
interface(dfa) {
operator map:: (op(seqaccess)) -> impl(solid).
operator list_range:: ()->impl(on_the_fly).
operator list:: ()->impl(solid).
operator fold:: (op(seqaccess)).
/* operator index:: (op(randaccess)). - BREAKS THE ANALYSIS. MAKE tree VIEWED AS COLLECTION */
/* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
}
-import raw("core/containers.lp")
+import raw("core/containers.lp").
// PROGRAM
XmlNode = type alias {
tag:: string,
/* attrs:: [string],*/
content:: string
}.
Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
XmlTree = type alias Tree(XmlNode).
test= function:: num; entry {
filename = "scripts/containers/Containers_Implementation_LinkedList1-data.xml" :: string.
docRaw = xmlParseFile(filename) :: xmlDocPtr.
tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
childrenRaw = tree["children"]:: [xmlNodePtr]; linkedlist(next, null).
size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count):: int {
count +1::int
}.
size
}

Event Timeline