Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2731332
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Mar 14, 4:37 AM
Size
244 KB
Mime Type
text/x-diff
Expires
Mon, Mar 16, 4:37 AM (1 d, 11 h)
Engine
blob
Format
Raw Data
Handle
243967
Attached To
rXR Xreate
View Options
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(®istry);
+ 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(®istry);
+ 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
Log In to Comment