Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2731339
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:38 AM
Size
205 KB
Mime Type
text/x-diff
Expires
Mon, Mar 16, 4:38 AM (1 d, 16 h)
Engine
blob
Format
Raw Data
Handle
243974
Attached To
rXR Xreate
View Options
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index fbe17ca..6574680 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,454 +1,454 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.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
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 skipIdent()
{
int kind = 0;
scanner->ResetPeek();
while ((kind = scanner->Peek()->kind) == _colon)
if (scanner->Peek()->kind != _ident)
return 0;
return kind;
}
bool checkParametersList()
{
return la->kind == _ident && skipIdent() == _lparen;
}
bool checkInfix()
{
return la->kind == _ident && skipIdent() == _ident;
}
bool checkIndex()
{
return la->kind == _ident && skipIdent() == _lbrack;
}
bool checkFuncDecl()
{
if (la->kind != _ident) return false;
int xkind = skipIdent();
Token* y = scanner->Peek();
return xkind == _assign && y->kind == _function;
}
bool checkAssignment()
{
scanner->ResetPeek();
Token* x = scanner->Peek();
return la->kind == _ident && x->kind == _assign;
}
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
ident = (letter | '_') {letter | digit | '_'}.
number = digit {digit}.
string = '"' { any } '"'.
function = "function".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
tagcolon = "::".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
Xreate = { ( RuleDecl | InterfaceData | Imprt | IF(checkFuncDecl()) FDecl | TDecl ) }.
Ident<std::wstring& name>
= ident {':' ident} (. name = t->val; .).
FDecl<> = (. std::wstring fname; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; .)
Ident<fname> assign function (. Function* f = new Function(fname); CodeScope* entry = f->getEntryScope(); .)
( Type<typOut> (. f->setReturnType(typOut); .)
| '(' [Ident<varname> tagcolon Type<typIn> (. f->addArg(std::move(varname), move(typIn)); .)
{',' Ident<varname> tagcolon Type<typIn> (. f->addArg(std::move(varname), move(typIn));.)
}] ')' tagcolon Type<typOut> (. f->setReturnType(typOut); .)
{';' FnTag<f> }
) BDecl<entry> (. entry->__body.bindType(move(typOut)); root.add(f); .)
.
/**
* TYPES
*
*/
TypeTerm<TypeAtom& typ> = (. std::wstring tid; .)
("string" | "int" | "num" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .)
.
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
| TypeTerm<typ3> (. typ = TypeAnnotation(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; .)
'{'
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()); .)
'}'.
TDecl = (. std::wstring ttag; TypeAnnotation t; 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)); .)
| 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)); .)
) '.'
.
VDecl<CodeScope* f> = (. std::wstring vname; Expression e; TypeAnnotation typ;.)
Ident<vname> assign ExprTyped<e, typ>
(. f->addDeclaration(move(vname), move(typ), move(e)); .)
.
BDecl<CodeScope* scope> = (. Expression body; TypeAnnotation typ; pushContextScope(scope); .)
'{' { (
IF(checkAssignment()) VDecl<scope> '.'
- | ExprTyped<body, typ> (. scope->setBody(body); popContextScope(); .)
-)}
+ | ExprTyped<body, typ> (. scope->setBody(body);.)
+)} (. popContextScope(); .)
'}'.
IfDecl<Expression& e, TypeAnnotation typ> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(context.scope)); TypeAnnotation typIf; .)
"if" '(' Expr<cond> ')' tagcolon Type<typIf> BDecl<&*blockTrue> "else" BDecl<&*blockFalse>
(. e = Expression(Operator::IF, {cond}); e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e, TypeAnnotation& typOut> =
(. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc; TypeAnnotation typEl, typAcc;
ManagedScpPtr block = root.add(new xreate::CodeScope(context.scope)); .)
"loop"
("map" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ')' tagcolon Type<typOut> BDecl<&*block>
(. e = Expression(Operator::MAP, {eIn});
e.addBindings({Atom<Identifier_t>(varEl)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
e.addBlock(block); .)
|"fold" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc> tagcolon Type<typAcc> ')' tagcolon Type<typOut> BDecl<&*block>
(. e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
block->addArg(Atom<Identifier_t>(varAcc), move(typAcc));
e.addBlock(block);
.)
).
SwitchDecl<Expression& eSwitch> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); .)
// ["switch" [tagcolon Type<typ> {';' MetaSimpExpr<tag>}]]
CaseDecl<eSwitch> {CaseDecl<eSwitch>}
.
CaseDecl<Expression& outer> = (. Expression inner(Operator::CASE, {});
ManagedScpPtr scopeCond = root.add(new xreate::CodeScope(context.scope));
ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scopeCond)); .)
"case"
( "default"
| CaseParams<&*scopeCond>
)
BDecl<&*scopeBody> (. inner.addBlock(scopeCond); inner.addBlock(scopeBody); outer.addArg(move(inner)); .)
.
CaseParams<CodeScope* scope> = (. Expression e; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
CaseParam<scope, guard>
{',' CaseParam<scope, guard>
} (. scope->setBody(guard); popContextScope(); .).
CaseParam<CodeScope* scope, Expression& guard> = (. TypeAnnotation argtyp; Expression condition; .)
(
IF(checkAssignment()) VDecl<scope>
| ExprTyped<condition, argtyp> (. guard.addArg(move(condition)); .)
).
/*============================ INTERFACES ===============================*/
Imprt<> =
"import" "raw" '(' string (. root.__rawImports.push_back(Atom<String_t>(t->val).get()); .)
')' '.' .
InterfaceData<> = "interface" '('
( "dfa" ')' InterfaceDFA
| "extern-c" ')' InterfaceExternC
| "cfa" ')' InterfaceCFA
).
InterfaceExternC<> = (.xreate::ExternData data; .)
'{' {IncludeExternDecl<data> | LibExternDecl<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)); .)
'.'.
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)); .).
/*============================ 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> '}' .
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))}); .)
'(' [ CalleeParams<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)); .)
).
RBody<const RuleArguments& args, const RuleGuards& guards> =
(. Expression e; std::wstring msg; .)
"warning" MetaExpr<e> ["message" string (. msg = t->val; .)
] (. root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
.
MetaOp< Operator& op> =
implic (. op = Operator::IMPL; .)
.
/*============================ Expressions ===============================*/
ExprTyped<Expression&e, TypeAnnotation& typ> = (. Expression tag; .)
Expr<e> [tagcolon Type<typ> (. e.bindType(move(typ)); .)
{';' MetaSimpExpr<tag> (. e.tags.emplace(tag.getValueString(), move(tag)); .)
}]
.
Expr< Expression& e> (. Operator op; Expression e2; .)
= SimExpr< e>
[ RelOp< op>
SimExpr< e2> (. e = Expression(op, {e, e2}); .)
].
SimExpr< Expression& e> (. Operator op; Expression e2; .)
= Term< e>
{ AddOp< op>
Term< e2> (. e = Expression(op, {e, e2});.)
}.
Term< Expression& e> (. Operator op; Expression e2; .)
= Factor< e>
{ MulOp< op>
Factor< e2> (. e = Expression(op, {e, e2}); .)
}.
Factor< Expression& e> (. std::wstring name; TypeAnnotation typ; .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); .)
'(' [CalleeParams<e>] ')'
|IF (checkIndex()) Ident<name>
lbrack CalleeParams<e> rbrack (. e.setOp(Operator::INDEX); e.setValue({Atom<Identifier_t>(name)}); .)
| Ident< name> (. e = Expression(Atom<Identifier_t>(name)); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
| LoopDecl<e, typ>
| IfDecl<e, typ>
| SwitchDecl<e>
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
| '-' Factor< e> (. e = Expression(Operator::NEG, {e}); .)
| '(' Expr<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(move(val)); keys.push_back(Atom<Identifier_t>(key)); .)
} '}' (. e.addBindings(keys.begin(), keys.end()); .)
.
ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
'['
[ Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
(".." Expr<eTo> (. e.addArg(std::move(eTo)); e.setOp(Operator::LIST_RANGE); .)
|{',' Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
} (. e.setOp(Operator::LIST); .)
) ] ']'.
CalleeParams<Expression& e> = (. Expression e2; TypeAnnotation typ; .)
ExprTyped<e2, typ> (. e.addArg(std::move(e2)); .)
{',' ExprTyped<e2, typ> (. e.addArg(std::move(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
| '<' (. op = Operator::LSS; .)
| '>' (. op = Operator::GTR; .)
).
END Xreate.
diff --git a/config/default.json b/config/default.json
index a0de9f7..7d03a30 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,50 +1,54 @@
{
"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"
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
"template": "default",
"templates": {
+ "basic": "EntryFunction*",
"default": "*-",
"types": "Types*-",
"containers": "Containers*-",
"ast": "AST*",
"non-containers": "*-Containers*",
- "libxml2": "libxml2*",
"log": "Logging*",
- "cfg": "CFG.testLoopContextExists"
+ "clang": "ClangAPI*"
+ "cfg": "CFG.*",
+ "skip": "SkipDetection*",
+ "raw-xml": "libxml2*",
+ "xml": "Xml.*"
}
}
}
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index d3e4c7b..269bdff 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,150 +1,149 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
find_package(LLVM REQUIRED CONFIG)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
link_directories(${LLVM_LIBRARY_DIRS})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
message ("MPATH:" ${CMAKE_MODULE_PATH})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
#find_package(Clang REQUIRED clangTooling libClang)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
set(POTASSCO_PATH "/opt/potassco/gringo" CACHE PATH "Path to gringo sources")
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
FILE (GLOB TEST_FILES ./tests/*.cpp)
message("TEST: " ${TEST_FILES})
set(SOURCE_FILES
${TEST_FILES}
./src/ast.cpp
./src/llvmlayer.cpp ./src/clasplayer.cpp
#./src/main.cpp
./src/utils.cpp
./src/passmanager.cpp
./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp ./src/pass/compilepass.cpp
./src/pass/cfgpass.cpp
./src/pass/logging.cpp
#./src/pass/rulespass.cpp
./src/instructions/instr-containers.cpp
./src/query/containers.cpp
./src/query/ptrvalid.cpp
./src/attachments.cpp
#${POTASSCO_PATH}/app/shared/src/clingocontrol.cc
#${POTASSCO_PATH}/app/pyclingo/src/clingo_lib.cc
)
set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
set(COCO_SOURCE_FILES
${COCO_PATH}/Parser.h
${COCO_PATH}/Scanner.h
${COCO_PATH}/Parser.cpp
${COCO_PATH}/Scanner.cpp
)
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES(${COCO_PATH} ./src)
INCLUDE_DIRECTORIES(${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
)
include_directories(${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/)
#execute_process(COMMAND ${COCO_PATH}/gen-xreate WORKING_DIRECTORY OUTPUT_VARIABLE COCO_OUTPUT)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
-add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} tests/testLibXml2.cpp src/ExternLayer.cpp src/ExternLayer.h)
+add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} src/ExternLayer.cpp src/ExternLayer.h)
set(COCO_TARGET grammar)
add_custom_target(${COCO_TARGET}
WORKING_DIRECTORY ${COCO_PATH}
)
add_custom_command(TARGET ${COCO_TARGET}
PRE_BUILD
COMMAND ${COCO_PATH}/gen-grammar
WORKING_DIRECTORY ${COCO_PATH}
)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
message(STATUS "BINARY DIR" ${CMAKE_BINARY_DIR})
#add_dependencies(${PROJECT_NAME} coverageTarget)
llvm_map_components_to_libnames(llvm_libs support core irreader all native nativecodegen)
message(STATUS "LLVM LIBS: " ${llvm_libs})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
)
message(STATUS "CLANG LIBS: " ${CLANG_LIBS})
message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS})
-add_definitions(-DWITH_THREADS=0)
+add_definitions(-DWITH_THREADS=1)
FUNCTION(PREPEND var prefix)
SET(listVar "")
FOREACH(f ${ARGN})
LIST(APPEND listVar "${prefix}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
-# -fprofile-arcs -ftest-coverage -O0
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
target_link_libraries(xreate ${GTEST_LIBRARIES} LLVM-${LLVM_VERSION} ${LIBCLASP_LIBS} ${CLANG_LIBS} pthread xml2 gcov tbb)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 6d8c5c1..3a866ab 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,276 +1,282 @@
//
// Created by pgess on 4/21/15.
//
#include "ExternLayer.h"
#include <cstdio>
#include <iostream>
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/TargetInfo.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
using namespace xreate;
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
class FinderCallbackTypeDecl : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
typeResult = decl->getUnderlyingType();
}
}
};
class FinderCallbackFunction : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
typeResult = decl->getType();
}
}
};
void
ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package)
{
__dictLibraries.emplace(name.get(), package.get());
}
void
ExternData::addIncludeDecl(Expression&& e)
{
assert(e.op == Operator::LIST_NAMED);
- //TODO implement Expression parsing(Array of Expr as vector<string>);
- int indexLib, indexHeaders;
+ //TODO ?? implement Expression parsing(Array of Expr as vector<string>);
for(size_t i=0, size=e.operands.size(); i<size; ++i)
{
std::string library = e.bindings.at(i);
assert(__dictLibraries.count(library));
std::string package = __dictLibraries.at(library);
Expression listHeaders = e.operands.at(i);
assert(listHeaders.op == Operator::LIST);
std::vector<std::string> headers;
std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
[](const Expression& o){
assert(o.__state == Expression::STRING);
return o.getValueString();
});
entries.emplace_back(ExternEntry{package, std::move(headers)});
}
}
void
ExternLayer::addExternalData(const std::vector<ExternEntry>& data){
entries.insert(entries.end(), data.begin(), data.end());
}
-ExternLayer::ExternLayer(LLVMLayer *llvm): __llvm(llvm), __datalayout(llvm->module)
+ExternLayer::ExternLayer(LLVMLayer *llvm)
+ : __datalayout(llvm->module), __llvm(llvm)
{}
std::vector<string>
ExternLayer::fetchPackageFlags(const ExternEntry& entry){
std::vector<string> args;
FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
+ if (linelen==1 && linebuf[0]==' ') continue;
if (linebuf[linelen-1 ] == ' ')
linebuf[linelen-1] = 0;
llvm::outs() << '<' << linebuf << "> ";
args.push_back(linebuf);
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (args);
}
std::vector<string>
ExternLayer::fetchPackageLibs(const ExternEntry& entry){
std::vector<string> libs;
FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
- if (linebuf[linelen-1 ] == ' ')
- linebuf[linelen-1] = 0;
+ if (linelen==1 && linebuf[0]==' ') continue;
+ if (linebuf[linelen-1 ] == ' ')
+ linebuf[linelen-1] = 0;
+ if (linelen>=2 && linebuf[0] == '-' && linebuf[1] == 'l'){
+ libs.push_back(linebuf + 2);
+ } else {
+ libs.push_back(linebuf);
+ }
llvm::outs() << '<' << linebuf << "> ";
- libs.push_back(linebuf);
-
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (libs);
}
void
ExternLayer::loadLibraries(vector<string>&& libs){
string msgErr;
for (const string& lib: libs) {
- if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(lib.c_str(), &msgErr)){
- llvm::errs()<<"\n"<<msgErr<<"\n";
+ const string& libName = string("lib")+lib+".so";
+ if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(libName.c_str(), &msgErr)){
+ llvm::errs()<<"\n"<<"Loading library "<<lib<<". " <<msgErr<<"\n";
}
}
}
void
ExternLayer::init(const AST* root) {
addExternalData(root->__externdata);
+ // TODO use default include path from 'clang -xc++ -E'
list<string> code;
std::vector<string> args{
"-I/usr/include"
,"-I/usr/local/include"
- ,"-I/usr/lib/llvm-3.6/lib/clang/3.6.0/include"
+ ,"-I/usr/lib/llvm-3.6/lib/clang/3.6.2/include"
// ,"-I/usr/lib/gcc/x86_64-linux-gnu/4.9/include"
// ,"-I/usr/include/x86_64-linux-gnu"
};
std::vector<string> libs;
boost::format formatInclude("#include \"%1%\"");
for(const ExternEntry& entry: entries)
{
llvm::outs()<<"[ExternC] Processing package: "<< entry.package << "\n";
llvm::outs()<<"[ExternC] args: ";
vector<string>&& args2 = fetchPackageFlags(entry);
args.insert(args.end(), args2.begin(), args2.end());
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
llvm::outs()<<"\n[ExternC] libs: ";
args2 = fetchPackageLibs(entry);
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
libs.insert(libs.end(), args2.begin(), args2.end());
llvm::outs()<<"\n[ExternC] headers: ";
std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
[&formatInclude](const string header ) {
string line = boost::str(formatInclude % header);
llvm::outs()<< "<" << line << "> ";
return line;
});
llvm::outs() << '\n';
}
- //TODO uncomment loadLibraries
- //loadLibraries(move(libs));
+ loadLibraries(move(libs));
ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
__cgo.reset(new CodeGenOptions);
__datalayout = llvm::DataLayout(ast->getASTContext().getTargetInfo().getTargetDescription());
__cgm.reset(new CodeGen::CodeGenModule(ast->getASTContext(), *__cgo, *__llvm->module, __datalayout, ast->getASTContext().getDiagnostics()));
};
bool
ExternLayer::isPointer(const clang::QualType &t) {
const clang::Type * tInfo = t.getTypePtr();
assert(tInfo);
return tInfo->isAnyPointerType();
}
llvm::Type*
ExternLayer::toLLVMType(const clang::QualType& t){
return __cgm->getTypes().ConvertType(t);
}
std::vector<std::string>
ExternLayer::getStructFields(const clang::QualType& ty)
{
clang::QualType t = ty;
if (isPointer(ty)){
const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
t = tPtr->getPointeeType();
}
assert(t.getTypePtr()->isRecordType());
const RecordType *record = t->getAsStructureType();
assert(record);
std::vector<std::string> result;
//FieldDecl* field: record->getDecl()->fields()
for (auto i=record->getDecl()->field_begin(); i!= record->getDecl()->field_end(); ++i){
result.push_back(i->getName());
}
return result;
}
clang::QualType
ExternLayer::lookupType(const std::string& id){
MatchFinder finder;
FinderCallbackTypeDecl callbackTypeDecl;
auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
finder.matchAST(ast->getASTContext());
assert(! callbackTypeDecl.typeResult.isNull());
return callbackTypeDecl.typeResult;
}
llvm::Function*
ExternLayer::lookupFunction(const std::string& name){
if (__functions.count(name)){
return __functions.at(name);
}
MatchFinder finder;
FinderCallbackFunction callback;
auto matcher = functionDecl(hasName(name)).bind("function");
finder.addMatcher(matcher, &callback);
finder.matchAST(ast->getASTContext());
assert(! callback.typeResult.isNull());
const QualType& tyFuncQual = callback.typeResult;
llvm::Type *tyRaw = __cgm->getTypes().ConvertType(tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
llvm::Function* function = llvm::Function::Create(tyRawFunc, llvm::GlobalValue::ExternalLinkage, name, __llvm->module);
__functions.emplace(name, function);
return function;
}
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 6db5f2f..ea80e4b 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,642 +1,642 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <clasplayer.h>
using namespace std;
namespace xreate{
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 (int i=0; i<args.size(); ++i)
+ for (size_t i=0; i<args.size(); ++i)
{
scope[t.bindings.at(i)] = args.at(i);
}
switch (t.__operator)
{
case TypeOperator::ARRAY:
{
assert(t.__operands.size()==1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, t.__size));
}
case TypeOperator::STRUCT:
{
assert(t.__operands.size());
std::vector<TypeAnnotation>&& pack = expandOperands(t.__operands);
auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack));
tnew.fields = t.fields;
return ExpandedType(move(tnew));
};
case TypeOperator::CALL:
{
std::string alias = t.__valueCustom;
//find in local scope:
TypeAnnotation ty;
if (scope.count(alias)) {
ty = scope.at(alias);
} else if (ast->__indexTypeAliases.count(alias)){
ty = ast->__indexTypeAliases.at(alias);
} else {
assert(false && "Undefined or external type");
}
std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
TypeAnnotation signature(TypeOperator::CALL, move(operands));
signature.__valueCustom = alias;
if (signatures.count(signature)) {
auto link = TypeAnnotation(TypeOperator::LINK, {});
link.conjuctionId = signatures.at(signature);
return ExpandedType(move(link));
}
int cid = signatures.size();
signatures[signature] = cid;
TypeAnnotation tyResult = expandType(ty, operands);
tyResult.conjuctionId = cid;
return ExpandedType(move(tyResult));
};
case TypeOperator::CUSTOM:
{
std::string alias = t.__valueCustom;
/*
if (signatures.count(alias)) {
return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
}
signatures[alias].emplace(t);
*/
//find in local scope:
if (scope.count(alias))
{
return expandType(scope.at(alias));
}
// find in general scope:
if(ast->__indexTypeAliases.count(alias)) {
return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
}
//if type is unknown keep it as is.
return ExpandedType(TypeAnnotation(t));
};
case TypeOperator::ACCESS:
{
std::string alias = t.__valueCustom;
ExpandedType tyAlias= ExpandedType(TypeAnnotation());
//find in local scope:
if (scope.count(alias)) {
tyAlias = expandType(scope.at(alias));
//find in global scope:
} else if((ast->__indexTypeAliases.count(alias))) {
tyAlias = expandType(ast->__indexTypeAliases.at(alias));
} else {
assert(false && "Undefined or external type");
}
assert(tyAlias->__operator == TypeOperator::STRUCT);
for (const string& field: t.fields){
auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
assert(fieldIt != tyAlias->fields.end() && "unknown field");
int fieldId = fieldIt - tyAlias->fields.begin();
tyAlias = expandType(tyAlias->__operands.at(fieldId));
}
return tyAlias;
}
case TypeOperator::TUPLE: {
assert(t.__operands.size());
std::vector<TypeAnnotation> pack;
pack.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation& t){
return expandType(t);
});
return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
}
case TypeOperator::NONE: {
return ExpandedType(TypeAnnotation(t));
}
default:
assert(false);
}
assert(false);
return ExpandedType(TypeAnnotation());
}
};
TypeAnnotation::TypeAnnotation()
{
}
TypeAnnotation::TypeAnnotation(const Atom<Type_t> &typ)
: __value(typ.get())
{
;
}
TypeAnnotation::TypeAnnotation (TypePrimitive typ)
: __value(typ)
{}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands)
{
}
TypeAnnotation::TypeAnnotation (TypeOperator op, std::vector<TypeAnnotation>&& operands)
: __operator(op), __operands(operands)
{}
TypeAnnotation::TypeAnnotation (llvm_array_tag, TypeAnnotation typ, int size)
:TypeAnnotation(TypeOperator::ARRAY, {typ})
{
__size=size;
}
bool
TypeAnnotation::operator< (const TypeAnnotation& t) const{
if (__operator != t.__operator) return __operator < t.__operator;
if (__operator == TypeOperator::NONE)
return __value < t.__value;
if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS){
if (__valueCustom != t.__valueCustom)
return __valueCustom < t.__valueCustom;
}
return __operands < t.__operands;
}
/*
TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
{}
*/
void
TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params)
{
bindings.reserve(params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident){return ident.get(); });
}
Expression::Expression(const Atom<Number_t>& number)
: __state(NUMBER), op(Operator::NONE), __valueD(number.get())
{
}
Expression::Expression(const Atom<String_t>& a)
: __state(STRING), op(Operator::NONE), __valueS(a.get())
{
}
Expression::Expression(const Atom<Identifier_t> &ident)
: __state(IDENT), op(Operator::NONE), __valueS(ident.get())
{
if (ident.get() == "null") {
__state = NONE;
}
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: __state(COMPOUND), op(oprt)
{
if (op == Operator::CALL)
{
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
operands.insert(operands.end(), params.begin()+1, params.end());
return;
}
operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt)
{
op = oprt;
switch (op)
{
case Operator::NONE:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg)
{
operands.push_back(arg);
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params)
{
addBindings(params.begin(), params.end());
}
void
Expression::bindType(TypeAnnotation&& t)
{
type = 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();
}
bool
Expression::isNone() const{
return (op == Operator::NONE && __state == NONE);
}
bool
Expression::isValid() const{
return (__state != INVALID);
}
Expression::Expression()
- : op(Operator::NONE), __state(INVALID)
+ : __state(INVALID), op(Operator::NONE)
{}
AST::AST()
{
}
void
AST::addInterfaceData(const ASTInterface& interface, Expression&& data ) {
__interfacesData.emplace(interface, move(data));
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
void
AST::addExternData(ExternData &&data) {
__externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
}
void
AST::add(Function* f)
{
__functions.push_back(f);
__indexFunctions[f->getName()] = __functions.size()-1;
}
void
AST::add(MetaRuleAbstract *r)
{
__rules.push_back(r);
}
void
AST::add(TypeAnnotation&& t, Atom<Identifier_t>&& alias){
__indexTypeAliases.emplace(alias.get(), t);
}
ManagedScpPtr
AST::add(CodeScope* scope)
{
this->__scopes.push_back(scope);
return ManagedScpPtr(this->__scopes.size()-1, &this->__scopes);
}
std::string
AST::getModuleName()
{
const std::string name = "moduleTest";
return name;
}
ManagedPtr<Function>
AST::findFunction(const std::string& name)
{
if (! __indexFunctions.count(name)) {
return ManagedFnPtr::Invalid();
}
return ManagedPtr<Function>(__indexFunctions.at(name), &__functions);
}
template<>
ManagedPtr<Function>
AST::begin<Function>()
{return ManagedPtr<Function>(0, &this->__functions);}
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>()
{return ManagedPtr<CodeScope>(0, &this->__scopes);}
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>()
{return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const
{
return TypesResolver(this)(t);
}
Expanded<TypeAnnotation>
AST::findType(const std::string& name){
// find in general scope:
if(__indexTypeAliases.count(name))
return expandType(__indexTypeAliases.at(name));
//if type is unknown keep it as is.
TypeAnnotation t(TypeOperator::CUSTOM, {});
t.__valueCustom = name;
return ExpandedType(move(t));
}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0))
{
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod)
{
__tags.emplace_back(tag, mod);
}
const std::vector<Tag>&
Function::getAnnotations() const
{
return __tags;
}
CodeScope*
Function::getEntryScope() const
{
return __entry;
}
void
CodeScope::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
{
- VID id = registerVar(std::move(const_cast<std::string&>(name.get())), std::move(typ));
+ registerVar(std::move(const_cast<std::string&>(name.get())), std::move(typ));
__args.push_back(name.get());
}
;
void
Function::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
{
__entry->addArg(move(name), move(typ));
}
void
Function::setReturnType(const TypeAnnotation &rtyp)
{
__entry->__definitions[0] = rtyp;
}
const std::string&
Function::getName() const
{
return __name;
}
CodeScope::CodeScope(CodeScope* parent)
:__parent(parent)
{}
CodeScope::~CodeScope()
{}
VID
CodeScope::registerVar(std::string&& name, TypeAnnotation &&typ)
{
__vartable[name] = ++__vCounter;
__definitions[__vCounter] = typ;
return __vCounter;
}
void
CodeScope::addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body)
{
VID id = registerVar(std::move(const_cast<string&>(name.get())), move(typ));
__declarations[id] = body;
}
void
CodeScope::setBody(const Expression &body)
{
__body = body;
}
TypeAnnotation&
CodeScope::findDefinition(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
assert(self->__definitions.count(symbol.identifier));
return self->__definitions[symbol.identifier];
}
Symbol
CodeScope::findSymbol(const std::string &name)
{
//search var in current block
if (__vartable.count(name))
{
VID vId = __vartable.at(name);
Symbol result{vId, this};
return result;
}
//search in parent scope
if (__parent)
{
return __parent->findSymbol(name);
}
//exception: Ident not found
- assert(false);
+ assert(false && "Symbol not found");
}
bool
CodeScope:: hasDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
return (self->__declarations.count(symbol.identifier));
}
const Expression&
CodeScope::findDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
if (! self->__declarations.count(symbol.identifier))
{
// no declaration exists
assert(false);
}
return self->__declarations[symbol.identifier];
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ)
{
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e)
{
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards))
{}
MetaRuleAbstract::~MetaRuleAbstract(){}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
- : MetaRuleAbstract(std::move(args), std::move(guards)), __condition(condition), __message(message.get())
+ : MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition)
{}
RuleWarning::~RuleWarning(){}
void
RuleWarning::compile(ClaspLayer& layer)
{
layer.addRuleWarning(*this);
}
bool operator< (const Symbol& s1, const Symbol& s2)
{
return (s1.scope < s2.scope) || (s1.scope==s2.scope && s1.identifier<s2.identifier);
}
bool operator== (const Symbol& s1, const Symbol& s2)
{
return (s1.scope == s2.scope) && (s1.identifier==s2.identifier);
}
}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 973ea60..c1ddc4b 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,518 +1,519 @@
#ifndef AST_H
#define AST_H
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "attachments.h"
#include "utils.h"
#include <algorithm>
namespace llvm{
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)
{
char buffer[32];
wcstombs(buffer, value.c_str(), 32);
__value = buffer;
}
Atom(std::string && name): __value(name) {}
const std::string& get() const{return __value; }
private:
std::string __value;
};
template<> class Atom<Number_t>
{
public:
Atom(wchar_t* value)
{
__value = wcstol(value, 0, 10);
}
Atom(int value)
: __value(value)
{}
double get()const {return __value; }
private:
double __value;
};
template<> class Atom<String_t>
{
public:
Atom(const std::wstring& value)
: __value(++value.begin(), --value.end())
{}
const std::string& get() const {return __value; }
private:
std::string __value;
};
enum class TypePrimitive {Bool, Int, Float, Num, String, I32, I8};
template<> class Atom<Type_t>
{
public:
Atom(wchar_t* value)
{
char buffer_[32];
wcstombs(buffer_, value, 32);
std::string buffer(buffer_);
if (buffer=="bool"){
__value = TypePrimitive ::Bool;
} else if (buffer=="int") {
__value = TypePrimitive::Int;
} else if (buffer=="float") {
__value = TypePrimitive::Float;
} else if (buffer=="num") {
__value = TypePrimitive::Num;
} else if (buffer=="string") {
__value = TypePrimitive::String;
}
}
Atom()
{
}
TypePrimitive get() const
{
return __value;
}
private:
TypePrimitive __value;
};
typedef Atom<Type_t> TypeAtom;
enum class TypeOperator{NONE, CALL, CUSTOM, 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);
bool operator< (const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId=-1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator
{
ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, INDEX, IF, SWITCH, CASE, LOGIC_AND
};
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()
{
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);
struct Expression
{
friend class CodeScope;
friend class ClaspLayer;
friend class CFGPass;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation&& t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isNone() const;
bool isValid() const;
- Operator op;
enum {INVALID, COMPOUND, IDENT, NUMBER, STRING, NONE} __state = INVALID;
+ Operator op;
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
TypeAnnotation type;
std::map<std::string, Expression> tags;
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
};
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom){
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
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 VID;
/*
class Expression: ExpressionAbstract
{
friend class CFGPass;
public:
llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
};
*/
typedef std::pair<VID, TypeAnnotation> VariableDefinition;
typedef std::pair<VID, Expression> VariableDeclaration;
typedef std::pair<Expression, TagModifier> Tag;
struct Symbol
{
VID identifier;
CodeScope * scope;
};
struct SymbolTags_t{};
template<>
struct AttachmentsDict<SymbolTags_t> {
typedef std::map<std::string, Expression> Data;
static const unsigned int key = 2;
};
bool operator< (const Symbol& s1, const Symbol& s2);
bool operator== (const Symbol& s1, const Symbol& s2);
class CodeScope
{
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent=0);
void setBody(const Expression& body);
void addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body);
void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
//TODO exclude forceCompile partz
Symbol findSymbol(const std::string &name);
static const Expression& findDeclaration(const Symbol& symbol);
static TypeAnnotation& findDefinition(const Symbol& symbol);
static bool hasDeclaration(const Symbol& symbol);
~CodeScope();
std::vector<std::string> __args;
Expression __body; //TODO move __body to __declarations[0]
SymbolAttachments attachments;
std::map<std::string, VID> __vartable;
/**
* definition of return type has variable index Zero(0)
*/
//TODO move __definitions to SymbolsAttachments data
std::unordered_map<VariableDefinition::first_type, VariableDefinition::second_type> __definitions;
std::unordered_map<VariableDeclaration::first_type, VariableDeclaration::second_type> __declarations;
protected:
VID __vCounter=1;
CodeScope* __parent;
std::list<CodeScope*> __storage;
VID registerVar(std::string&& name, TypeAnnotation &&typ);
};
class Function
{
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
void addTag(Expression&& tag, const TagModifier mod);
void setReturnType(const TypeAnnotation& rtyp);
const std::string& getName() const;
const std::vector<Tag>& getAnnotations() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
private:
std::vector<Tag> __tags;
};
class ExternData;
struct ExternEntry {
std::string package;
std::vector<std::string> headers;
};
typedef Expanded<TypeAnnotation> ExpandedType;
enum ASTInterface {
CFA, DFA, Extern
};
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);
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;
+ std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
std::map<std::string, unsigned int> __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);
private:
ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
// ***** TYPES SECTION END *****
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
}
#endif // AST_H
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index 751e072..c074c43 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,611 +1,623 @@
#include "clasplayer.h"
-#include <clasp/program_builder.h> // for defining logic programs
-#include <clasp/unfounded_check.h> // unfounded set checkers
-#include <clasp/model_enumerators.h> // for enumerating answer sets
-#include <clasp/clasp_facade.h>
-
#include <iostream>
-#include <clingo/clingocontrol.hh>
#include "utils.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
+#include <gringo/scripts.hh>
using namespace std;
namespace xreate {
void
ClaspLayer::printWarnings(std::ostream& out)
{
const std::string warningTag = "warning";
auto warningsRange = __model.equal_range(warningTag);
for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) {
unsigned int warningId;
Gringo::Value params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Value>(warning->second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
ClaspLayer::onModel(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");
for (Gringo::Value atom : model.atoms(Gringo::Model::ATOMS)) {
atom.print(cout);
cout <<" | "<< endl;
if (*atom.name() == atomBindVar || *atom.name() == atomBindFunc){
string name = *std::get<1>(parse<Gringo::Value, Gringo::Value>(atom)).name();
__model.emplace(move(name), move(atom));
continue;
}
__model.emplace(*atom.name(), move(atom));
}
return true;
}
list<string>
multiplyLists(list<list<string>> &&lists) {
typedef list<string> StringList;
assert(lists.size());
StringList result(*lists.begin());
lists.pop_front();
boost::format concat("%s, %s");
for (StringList &list: lists) {
StringList::const_iterator end = result.end();
for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
if (list.size() == 0) continue;
StringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
result.push_back(str(concat %(*expr1I) %(*expr2I)));
*expr1I = str(concat %(*expr1I) %(*expr2I));
}
}
return result;
}
void
ClaspLayer::setCFAData(CFAGraph &&graph) {
cfagraph = graph;
}
void
ClaspLayer::addDFAData(DFAGraph &&graph)
{
dfaData = graph;
std::set<SymbolPacked> symbols;
ostream &cout = __partGeneral;
cout << endl << "%\t\tStatic analysis: DFA" << endl;
std::vector<std::pair<SymbolPacked, SymbolPacked>>::iterator i1;
std::vector<DFGConnection>::iterator i2;
- boost::format format3Args("(%1%, %2%, %3%)");
+ boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
boost::format format2Args("(%1%, %2%)");
for (i1= dfaData.__edges.begin(), i2 = dfaData.__data.begin(); i1!= dfaData.__edges.end(); ++i1, ++i2 )
{
string edgeName;
switch (*i2)
{
case DFGConnection::OPT: edgeName = "opt"; break;
case DFGConnection::ALIAS: edgeName = "alias"; break;
case DFGConnection::PROTO: edgeName = "proto"; break;
}
- cout << "dfa_connection"<< (format3Args
- %(format2Args %(i1->first.identifier) %(i1->first.scope))
- %(format2Args %(i1->second.identifier) %(i1->second.scope))
- %edgeName)
- << "." <<endl;
+ cout << formatDfaConnection
+ %(format2Args %(i1->first.identifier) %(i1->first.scope)).str()
+ %(format2Args %(i1->second.identifier) %(i1->second.scope)).str()
+ %edgeName
+ << " %" <<getHintForPackedSymbol(i1->first) << " - " << getHintForPackedSymbol(i1->second)
+ <<endl;
symbols.insert(i1->first);
symbols.insert(i1->second);
}
boost::format formatBind("bind(%1%, %2%).");
for (const pair<SymbolPacked, Expression>& tag: dfaData.__tags)
{
for (string variant: compile(tag.second)) {
cout << (formatBind
% (format2Args %(tag.first.identifier) %(tag.first.scope))
% (variant))
+ << "%" << getHintForPackedSymbol(tag.first)
<< endl;
}
symbols.insert(tag.first);
}
for (const SymbolPacked& s: symbols)
{
- cout << "v(" << format2Args % (s.identifier) % arg(s.scope) << ")."<<endl;
+ cout << "v(" << format2Args % (s.identifier) % (s.scope) << ")."
+ << " %" << getHintForPackedSymbol(s)
+ <<endl;
}
}
void
ClaspLayer::involveCFAData() {
ostream &cout = __partTags;
const std::string& atomBinding = Config::get("clasp.bindings.function");
const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
//show function tags
int counterTags = 0;
boost::format formatFunction("function(%1%).");
boost::format formatBind("%1%(%2%, %3%).");
for (auto function: cfagraph.__nodesFunction.left) {
cout << formatFunction % (function.second) << std::endl;
for (const auto& tag_: boost::make_iterator_range(cfagraph.__functionTags.equal_range(function.first))){
const Tag& tag = tag_.second;
list<string> tagRaw = compile(tag.first);
assert(tagRaw.size() == 1);
cout << formatBind
% (atomBinding)
% (function.second)
% (tagRaw.front())
<< endl;
++counterTags;
}
}
if (counterTags == 0) {
cout << "%no tags at all" << endl;
}
//show scope tags:
boost::format formatScope("scope(%1%).");
for (auto scope: __indexScopes) {
//std::string function = scope.first.
cout << formatScope % scope.second << std::endl;
}
counterTags = 0;
- boost::format formatScopeBind("(%1%(%2%, %3%).");
+ boost::format formatScopeBind("%1%(%2%, %3%).");
for (auto entry: cfagraph.__scopeTags) {
ScopePacked scopeId = entry.first;
const Expression& tag = entry.second;
list<string> tagRaw = compile(tag);
assert(tagRaw.size() == 1);
cout << formatScopeBind % atomBindingScope % scopeId %(tagRaw.front()) << endl;
++counterTags;
}
if (counterTags == 0) {
cout << "%no tags at all" << endl;
}
cout << endl << "%\t\tStatic analysis: CFA" << endl;
boost::format formatCall("call(%1%, %2%).");
for (const auto &relation: cfagraph.__relations) {
const ScopePacked scopeFrom = relation.first;
const string& functionTo = cfagraph.__nodesFunction.left.at(relation.second);
cout << formatCall % (scopeFrom) % (functionTo) << endl;
}
}
void
ClaspLayer::addRuleWarning(const RuleWarning &rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch (argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list<string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return compile(guard);
});
const list<string>& guards = multiplyLists(std::move(guardsRaw));
list<string> &&branches = compileNeg(rule.__condition);
boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
for (const string &guardsJoined: guards)
for (const string &branch: branches) {
unsigned int hook = registerWarning(string(rule.__message));
__partGeneral << formatWarning
%(hook)
%(boost::algorithm::join(vars, ", "))
%(branch)
%(guardsJoined)
%(boost::algorithm::join(domains, ", "))
<<endl;
}
}
std::list<std::string>
ClaspLayer::compile(const Expression &e) const {
list<string> result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
std::list<list<string>> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[this](const Expression &e) {
return compile(e);
});
list<string> &&operands_ = multiplyLists(std::move(operands));
result.push_back(boost::str(boost::format("%1%(%2%)") % (e.__valueS) % (boost::algorithm::join(operands_, ", "))));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::NONE: {
switch (e.__state) {
case Expression::IDENT:
result.push_back(e.__valueS);
break;
case Expression::NUMBER:
result.push_back(to_string(e.__valueD));
break;
default:
assert(true);
}
break;
}
+
+ default: break;
}
if (e.isNone()){
result.push_back(e.__valueS);
}
assert(result.size());
return result;
}
std::list<std::string>
ClaspLayer::compileNeg(const Expression &e) const {
list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
list<string> operands1 = compile(e.operands.at(0));
list<string> operands2 = compile(e.operands.at(1));
boost::format formatNeg("%1%, not %2%");
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back(rawOp.front());
break;
};
default:
assert(true);
}
return result;
}
unsigned int
ClaspLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
ClaspLayer::involveImports() {
ostream &out = __partGeneral;
for (string fn: ast->__rawImports)
{
std::ifstream file(fn);
if (!file) continue;
while(!file.eof()){
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
ClaspLayer::addRawScript(std::string&& script){
__partGeneral << script;
}
void
ClaspLayer::run() {
involveImports();
involveCFAData();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
- const char *argv[] = {nullptr, nullptr};
+ std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
- ClingoLib ctl(moduleDefault, 2, argv);
-
- //prg.add("p", ["t"], "q(t).")
- Gringo::FWStringVec vars{};
- ctl.add("base", vars, program.str());
+ Gringo::Scripts scriptsDefault(moduleDefault);
+ ClingoLib ctl(scriptsDefault, 0, args.data());
- //prg.ground([("p", [2])])
- Gringo::Control::GroundVec vals{std::make_pair("base", Gringo::FWValVec {})};
- ctl.ground(vals, Gringo::Any());
+ ctl.add("base", {}, program.str());
+ ctl.ground({{"base", {}}}, nullptr);
- //solve
- Gringo::Control::Assumptions as;
- Gringo::SolveResult result = ctl.solve(Gringo::Control::ModelHandler([&](Gringo::Model const &model) {
- return this->onModel(model);
- }), std::move(as));
+// solve
+ Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
+ this->onModel(model);
+ return true;
+ }, {});
if (result == Gringo::SolveResult::SAT) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
- // invoke all query plugins to process clasp data
+// invoke all query plugins to process clasp data
for (IQuery* q: __queries)
{
q->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
- ClaspLayer::ModelRange
+ ClaspLayer::ModelFragment
ClaspLayer::query(const std::string& atom)
{
if (! __model.count(atom)){
return boost::none;
}
- return ModelRange(__model.equal_range(atom));
+ return ModelFragment(__model.equal_range(atom));
}
ScopePacked
ClaspLayer::pack(CodeScope* scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
SymbolPacked
ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
SymbolPacked result;
result.scope = pack(symbol.scope);
result.identifier = symbol.identifier;
+ __indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
ClaspLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
};
-
+ std::string
+ ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
+ auto result = __indexSymbolNameHints.find(symbol);
+ return (result == __indexSymbolNameHints.end())? "" : result->second;
+ }
/*
void AspOutPrinter::reportSolution(const Clasp::Solver&, const Clasp::Enumerator&, bool complete) {
if (complete) std::cout << "No more models!" << std::endl;
else std::cout << "More models possible!" << std::endl;
}
void AspOutPrinter::reportModel(const Clasp::Solver& s, const Clasp::Enumerator&) {
std::cout << "Model " << s.stats.solve.models << ": \n";
// get the symbol table from the solver
const Clasp::AtomIndex& symTab = *s.strategies().symTab;
for (Clasp::AtomIndex::const_iterator it = symTab.begin(); it != symTab.end(); ++it)
{
// print each named atom that is true w.r.t the current assignment
}
std::cout << std::endl;
}
*/
/*****************************************
* CFAGraph
*****************************************
*/
void
CFAGraph::addFunctionNodeTags(const std::string& function, const std::vector<Tag>&tags) {
unsigned int fid = registerNodeFunction(function);
for (Tag tag: tags){
__functionTags.emplace(fid, tag);
}
}
void
CFAGraph::addScopeNodeTags(const ScopePacked& scope, const std::vector<Expression>& tags){
for (Expression tag: tags){
__scopeTags.emplace(scope, tag);
}
}
void
CFAGraph::addLink(const ScopePacked& scopeFrom, const std::string& functionTo) {
unsigned int idFuncTo = registerNodeFunction(functionTo);
__relations.emplace(scopeFrom, idFuncTo);
}
unsigned int
CFAGraph::registerNodeFunction(const std::string& fname){
auto pos = __nodesFunction.left.insert(make_pair(__nodesFunction.size(), fname));
return pos.first->first;
}
/*****************************************
* DFAGraph
*****************************************
*/
class VisitorAddTag: public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& symbol){
__graph->__tags.emplace(symbol, move(__tag));
}
void operator()(SymbolTransient& symbol){
symbol.tags.push_back(move(__tag));
}
void operator()(const SymbolInvalid& symbol){
assert(false && "Undefined behaviour");
}
VisitorAddTag(DFAGraph* const dfagraph, Expression&& tag):
__graph(dfagraph), __tag(tag) {}
private:
DFAGraph* const __graph;
Expression __tag;
};
class VisitorAddLink: public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& nodeFrom){
if (!__graph->linkExists(__nodeTo, nodeFrom))
{
__graph->__edges.emplace_back(__nodeTo, nodeFrom);
__graph->__data.push_back(__link);
DFAGraph::EdgeId eid = __graph->__edges.size()-1;
__graph->__outEdges.emplace(nodeFrom, eid);
}
}
- void operator()(const SymbolTransient& symbol){
+ void operator()(const SymbolTransient& symbolFrom){
+ if (__link != DFGConnection::ALIAS){
+ assert(false && "Undefined behaviour");
+ }
+
+ for (const Expression& tag: symbolFrom.tags){
+ __graph->__tags.emplace(__nodeTo, tag);
+ }
}
- void operator()(const SymbolInvalid& symbol){
+ void operator()(const SymbolInvalid&){
+ if (__link == DFGConnection::ALIAS) return;
+ if (__link == DFGConnection::OPT) return;
+
assert(false && "Undefined behaviour");
}
VisitorAddLink(DFAGraph* const dfagraph, const SymbolPacked& nodeTo, DFGConnection link):
__graph(dfagraph), __nodeTo(nodeTo), __link(link) {}
private:
DFAGraph* const __graph;
SymbolPacked __nodeTo;
DFGConnection __link;
};
bool
DFAGraph::linkExists(const SymbolPacked& node1, const SymbolPacked& node2)
{
auto range = __outEdges.equal_range(node2);
for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
{
if (__edges[edge->second].second == node1)
return true;
}
return false;
}
void
DFAGraph::addLink(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
VisitorAddLink visitor(this, nodeTo, link);
boost::apply_visitor(visitor, nodeFrom);
}
void
DFAGraph::addTag(SymbolNode& node, Expression&& tag) {
VisitorAddTag visitor(this, move(tag));
boost::apply_visitor(visitor, node);
}
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2)
{
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
void ClaspLayer::registerdQuery(IQuery *query) {
__queries.push_back(query);
}
}
diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h
index 85acd90..c89196a 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,200 +1,202 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_H
#include <ast.h>
-#include <gringo/control.hh>
+#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <boost/bimap.hpp>
#include <boost/optional.hpp>
#include <list>
namespace xreate {
typedef unsigned int ScopePacked;
class CFAGraph {
friend class ClaspLayer;
public:
void addFunctionNodeTags(const std::string& function, const std::vector<Tag>&tags);
void addScopeNodeTags(const ScopePacked& scope, const std::vector<Expression>&tags);
void addLink(const ScopePacked& scopeFrom, const std::string& functionTo);
//void print(std::ostream &cout) const;
private:
std::map<ScopePacked, unsigned int> __relations;
boost::bimap<unsigned int, std::string > __nodesFunction;
std::multimap<unsigned int, Tag> __functionTags;
std::multimap<ScopePacked, Expression> __scopeTags;
unsigned int registerNodeFunction(const std::string& fname);
};
struct SymbolPacked
{
VID identifier;
ScopePacked scope;
};
struct SymbolTransient{
std::list<Expression> tags;
};
struct SymbolInvalid{};
typedef boost::variant<SymbolPacked, SymbolTransient, SymbolInvalid> SymbolNode;
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
enum class DFGConnection{
ALIAS, OPT, PROTO};
class VisitorAddTag;
class VisitorAddLink;
class DFAGraph
{
friend class ClaspLayer;
friend class VisitorAddTag;
friend class VisitorAddLink;
public:
void addTag(SymbolNode& node, Expression&& tag);
void addLink(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link);
bool linkExists(const SymbolPacked& node1, const SymbolPacked& node2);
private:
typedef unsigned int EdgeId;
std::vector<std::pair<SymbolPacked, SymbolPacked>> __edges;
std::multimap<SymbolPacked, EdgeId> __outEdges;
std::vector<DFGConnection> __data;
std::multimap<SymbolPacked, Expression> __tags;
};
class IQuery {
public:
virtual void init(ClaspLayer* clasp)=0;
virtual ~IQuery() {}
};
class ClaspLayer {
public:
AST *ast;
DFAGraph dfaData;
CFAGraph cfagraph;
ClaspLayer();
void registerdQuery(IQuery* query);
void addFunctionTags(const std::string &function, const std::vector<Tag> &tags);
void setCFAData(CFAGraph &&graph);
void addDFAData(DFAGraph &&graph);
void addRuleWarning(const RuleWarning &rule);
void run();
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Value& atom);
typedef std::multimap<std::string, Gringo::Value>::const_iterator ModelIterator;
- typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelRange;
- ModelRange query(const std::string& atom);
+ typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelFragment;
+ ModelFragment query(const std::string& atom);
ScopePacked pack(CodeScope* scope);
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
Symbol unpack(const SymbolPacked& symbol);
+ std::string getHintForPackedSymbol(const SymbolPacked& symbol);
void addRawScript(std::string&& script);
private:
// all query plugins to process clasp data
std::list<IQuery*> __queries;
std::multimap<std::string, Gringo::Value> __model;
std::map<unsigned int, std::string> __warnings;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
+ std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<CodeScope*> __registryScopes;
void printWarnings(std::ostream& out);
bool onModel(Gringo::Model const &model);
std::list<std::string> compile(const Expression &e) const;
std::list<std::string> compileNeg(const Expression &e) const;
unsigned int registerWarning(std::string &&message);
void involveImports();
void involveCFAData();
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Value& atom)
{
return atom.num();
}
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Value& atom)
{
return *atom.string();
}};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Value& atom)
{
auto result = ClaspLayer::parse<unsigned int, unsigned int>(atom);
return SymbolPacked{std::get<0>(result), std::get<1>(result)};
}};
template<>
struct ParseImplAtom<Gringo::Value> {
static Gringo::Value get(const Gringo::Value& atom)
{
return atom;
}};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
{
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element<tupleSize - index, Tuple>::type ElType;
ElType& el = std::get<tupleSize - index>(tup);
Gringo::Value atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index-1>::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0>
{
static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
{}
};
template<class ...Types>
std::tuple<Types...>
ClaspLayer::parse(const Gringo::Value& atom)
{
typedef std::tuple<Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().begin());
return tup;
}
}
#endif
diff --git a/cpp/src/instructions/instr-containers.cpp b/cpp/src/instructions/instr-containers.cpp
index 5f7bfbc..793aec7 100644
--- a/cpp/src/instructions/instr-containers.cpp
+++ b/cpp/src/instructions/instr-containers.cpp
@@ -1,470 +1,501 @@
#include "instr-containers.h"
#include "llvmlayer.h"
#include "ast.h"
#include "query/containers.h"
#include "query/ptrvalid.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
-
+#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
CompilePass::CodeScopeUnit* scope = context.scope; \
CompilePass::FunctionUnit* function = context.function; \
Instructions::Instructions(CompilePass::Context ctx)
: context(ctx), tyNum (static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num)))))
{}
llvm::Value*
Instructions::compileMapSolid(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT
//initialization
std::string varIn = expr.getOperands()[0].getValueString();
Symbol symbolIn = scope->scope->findSymbol(varIn);
ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
size_t size = implIn.size;
CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__args[0];
Iterator* it = Iterator::create(context, symbolIn);
llvm::Value *rangeFrom = it->begin();
llvm::Value *rangeTo = it->end();
//definitions
ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
llvm::IRBuilder<> &builder = llvm->builder;
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postloop", function->raw);
Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
// * initial check
Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
// create PHI:
builder.SetInsertPoint(blockLoop);
llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// loop body:
Value* elIn = it->get(stateLoop, varEl);
CompilePass::CodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
scopeLoopUnit->bindArg(elIn, move(varEl));
Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop,llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, blockLoop);
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
Instructions::compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string hintRetVar)
{
EXPAND_CONTEXT
+ UNUSED(function);
//TODO find out symbol identifier in order to name it in raw llvm;
llvm::Value* data = scope->compileSymbol(dataSymbol);
const Expression& decl = CodeScope::findDeclaration(dataSymbol);
if (decl.op == Operator::LIST) {
assert(indexes.size() == 1);
return llvm->builder.CreateExtractElement(data, indexes[0], NAME("el"));
}
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
Value *pEl = llvm->builder.CreateGEP(data, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
Instructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx){
EXPAND_CONTEXT
-
+ UNUSED(scope);
TypeUtils types(llvm);
std::vector<std::string>&& fields = types.getStructFields(t);
for (unsigned i=0, size = fields.size(); i<size; ++i){
if (fields.at(i) == idx){
std::vector<llvm::Value*> refs;
llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::ConstantInt* zero = llvm::ConstantInt::get(tyInt, 0, false);
llvm::BasicBlock *blockSafe = llvm::BasicBlock::Create(llvm::getGlobalContext(), "safe", function->raw);
// safety check: not null ptr
Symbol s;
if (! QueryPtrValid::assertValidPtr(s)){
PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
llvm->initExceptionBlock(blockException);
}
llvm->builder.SetInsertPoint(blockSafe);
std::vector<Value*> indexes;
//dereference pointer
if (types.isPointer(t)){
indexes.push_back(zero);
}
indexes.push_back(ConstantInt::get(tyInt, i));
Value* addr = llvm->builder.CreateGEP(aggregate, indexes);
return llvm->builder.CreateLoad(addr);
}
}
assert(false && "not found required struct field");
}
llvm::Value*
Instructions::compileFold(const Expression& fold, const std::string& hintRetVar)
{
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = scope->scope->findSymbol(fold.getOperands()[0].getValueString());
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
llvm::Value* rangeFrom = it->begin();
llvm::Value* rangeTo = it->end();
llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
- llvm::Value* valSat;
+ llvm::Value* valSat = nullptr;
bool flagHasSaturation = false; //false; // TODO add `saturation` ann.
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
llvm::BasicBlock *blockEarly = llvm::BasicBlock::Create(llvm::getGlobalContext(), "earlyret", function->raw);
// * initial check
Value* condBefore = llvm->builder.CreateICmpNE(rangeFrom, rangeTo);
llvm->builder.CreateCondBr(condBefore, blockLoop, blockEarly);
llvm->builder.SetInsertPoint(blockEarly);
llvm->builder.CreateRet(accumInit);
+ //TODO implement saturation; add unittests;
// Saturation check
if (flagHasSaturation)
{
Value* condSat = llvm->builder.CreateICmpNE(accumInit, valSat);
llvm->builder.CreateCondBr(condSat, blockLoop, blockAfterLoop);
}
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(tyNum, 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *stateLoop = llvm->builder.CreatePHI(rangeFrom->getType(), 2, "foldIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// * loop body
CodeScope* scopeLoop = fold.blocks.front();
CompilePass::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(stateLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * break checks, continue checks
if (flagHasSaturation)
{
llvm::BasicBlock *blockChecks = llvm::BasicBlock::Create(llvm::getGlobalContext(), "checks", function->raw);
Value* condSat = llvm->builder.CreateICmpNE(accumNext, valSat);
llvm->builder.CreateCondBr(condSat, blockChecks, blockAfterLoop);
llvm->builder.SetInsertPoint(blockChecks);
}
// * computing next iteration state
Value *stateLoopNext = it->move(stateLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
stateLoop->addIncoming(stateLoopNext, llvm->builder.GetInsertBlock());
// * next iteration checks
Value* condAfter = llvm->builder.CreateICmpNE(stateLoopNext, rangeTo);
llvm->builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
llvm::Value*
Instructions::compileIf(const Expression& exprIf, const std::string& hintRetVar)
{
EXPAND_CONTEXT
//initialization:
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
llvm::BasicBlock *blockAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", function->raw);
llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", function->raw);
llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
llvm::PHINode *ret = builder.CreatePHI(tyNum, 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
+
+//TODO implement switch
llvm::Value*
Instructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar){
EXPAND_CONTEXT
- llvm::IRBuilder<>& builder = llvm->builder;
-
+ UNUSED(scope);
+ UNUSED(function);
+ UNUSED(llvm);
+ return nullptr;
+ //llvm::IRBuilder<>& builder = llvm->builder;
//builder.CreateSwitch()
-
}
llvm::Value*
Instructions::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
+ UNUSED(scope);
+ UNUSED(function);
const size_t& __size = expr.getOperands().size();
const Expression& __data = expr;
ArrayType* typList = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I32, __size))));
Type*typI32 = llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::I32)));
std::vector<Constant *> list;
list.reserve(__size);
const std::vector<Expression> operands = __data.getOperands();
std::transform(operands.begin(), operands.end(), std::inserter(list, list.begin()),
[typI32](const Expression& e){return ConstantInt::get(typI32, e.getValueDouble());});
Value* listSource = ConstantArray::get(typList, ArrayRef<Constant*>(list));
/*
Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
*/
return listSource;
}
llvm::Value*
Instructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar)
{
EXPAND_CONTEXT
+ UNUSED(function);
+ UNUSED(scope);
- size_t size = data.size();
Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm::getGlobalContext()));
//ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
/*
std::vector<Constant *> chars;
chars.reserve(size+1);
for (size_t i=0; i< size; ++i){
chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
}
chars[size] = ConstantInt::get(typI8, 0);
*/
Value* rawData = ConstantDataArray::getString(llvm::getGlobalContext(), data);
Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 1, false));
llvm->builder.CreateStore(rawData, rawPtrData);
return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
}
template<ImplementationType I>
class IteratorForward;
template<>
class IteratorForward<ON_THE_FLY> : public Iterator {
private:
LLVMLayer* llvm;
const xreate::Symbol current;
const Symbol source;
const ImplementationLinkedList linkedlist;
CodeScope* const sourceScope;
//TODO initialize ans mark as const (three fields)
CompilePass::CodeScopeUnit* sourceUnit;
- CompilePass::FunctionUnit* function;
+ CompilePass::FunctionUnit* function; //TODO is used somewhere?
const Expression& sourceDecl;
CompilePass::Context context;
llvm::Type* sourceRawType =nullptr;
public:
IteratorForward(CompilePass::Context ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
- : context(ctx), source(implementation.source), current(s), sourceScope(source.scope), sourceDecl(CodeScope::findDeclaration(source)),
- linkedlist(source), sourceUnit(new CompilePass::CodeScopeUnit(source.scope, ctx.function, ctx.pass)), llvm(ctx.pass->man->llvm)
+ : llvm(ctx.pass->man->llvm), current(s), source(implementation.source), linkedlist(source), sourceScope(source.scope), sourceUnit(new CompilePass::CodeScopeUnit(source.scope, ctx.function, ctx.pass)),
+ sourceDecl(CodeScope::findDeclaration(source)),
+ context(ctx)
{
}
llvm::Value* begin() {
switch(sourceDecl.op) {
case xreate::Operator::LIST:
{
sourceRawType = Type::getInt32Ty(llvm::getGlobalContext());
return ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 0);
};
case xreate::Operator::LIST_RANGE:{
assert(sourceDecl.operands.size()==2);
llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
sourceRawType = result->getType();
return result;
};
+
+ default: break;
}
if (linkedlist){
llvm::Value* result = sourceUnit->process(sourceDecl);
sourceRawType = result->getType();
return result;
}
assert(false);
}
llvm::Value* end(){
switch(sourceDecl.op) {
case xreate::Operator::LIST: {
size_t idLast = sourceDecl.operands.size() - 1;
return ConstantInt::get(sourceRawType, idLast);
}
case xreate::Operator::LIST_RANGE: {
assert(sourceDecl.operands.size() == 2);
return sourceUnit->process(sourceDecl.operands.at(1));
};
+
+ default: break;
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
+
+ assert(false && "Unknown declaration");
+ return nullptr;
}
llvm::Value* get(Value* index,const std::string& hintRetVar="") override{
const Expression& currentDecl = CodeScope::findDeclaration(current);
switch (currentDecl.op) {
case xreate::Operator::LIST: {
- llvm::Value* currentValue = sourceUnit->process(currentDecl); //TODO re check is it right scope(source) to compilation currentDecl
+ //TODO re check is it right scope(source) to compilation currentDecl. Write unittests for this.
+ //llvm::Value* currentValue = sourceUnit->process(currentDecl);
return Instructions(context).compileArrayIndex(current, vector<Value *>{index});
};
case xreate::Operator::LIST_RANGE: {
return index;
};
case xreate::Operator::MAP: {
assert(currentDecl.getOperands().size()==1);
assert(currentDecl.bindings.size());
assert(currentDecl.blocks.size());
CodeScope* scopeLoop = currentDecl.blocks.front();
const std::string& varIn = currentDecl.getOperands()[0].getValueString();
std::string varEl = currentDecl.bindings[0];
const Symbol& symbIn = current.scope->findSymbol(varIn);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
Value* elIn = it->get(index, varEl);
CompilePass::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(elIn, std::move(varEl));
return unitLoop->compile();
}
case xreate::Operator::NONE: {
assert(currentDecl.__state==Expression::IDENT);
const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
return it->get(index);
};
+
+ default: break;
}
if (linkedlist){
return index;
}
+
+ assert(false && "Unknown declaration");
+ return nullptr;
}
llvm::Value* move(Value* index, const std::string& hintRetVar) override{
switch(sourceDecl.op)
{
case xreate::Operator::LIST:
case xreate::Operator::LIST_RANGE:
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
+
+ default: break;
}
if (linkedlist){
ExpandedType tySource = llvm->ast->expandType(sourceScope->findDefinition(source));
assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
assert(tySource->__operands.size());
return Instructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
}
+
+ assert(false && "Unknown declaration");
+ return nullptr;
}
};
Iterator*
Iterator::create(CompilePass::Context context, const Symbol& var){
const Implementation& data = Query::queryImplementation(var);
switch(data.impl){
case ON_THE_FLY:
return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
default: assert(true);
}
+
+ assert(false && "Unknown declaration");
+ return nullptr;
}
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 2afa47c..0e34bb4 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,249 +1,246 @@
#include "ast.h"
#include "llvmlayer.h"
#include "ExternLayer.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include <iostream>
using namespace llvm;
using namespace xreate;
using namespace std;
LLVMLayer::LLVMLayer(AST* root)
- :builder(getGlobalContext()), ast(root)
-{
+ : ast(root), builder(getGlobalContext()) {
module = new llvm::Module(root->getModuleName(), llvm::getGlobalContext());
layerExtern = new ExternLayer(this);
layerExtern->init(root);
}
void*
LLVMLayer::getFunctionPointer(llvm::Function* function){
uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
return (void*) entryAddr;
}
void
LLVMLayer::initJit(){
std::string ErrStr;
LLVMInitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::EngineBuilder builder((std::unique_ptr<llvm::Module>(module)));
jit = builder
.setEngineKind(llvm::EngineKind::JIT)
.setErrorStr(&ErrStr)
.setVerifyModules(true)
.create();
}
void
LLVMLayer::print(){
llvm::PassManager<llvm::Module> PM;
PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
PM.run(*module);
}
llvm::BasicBlock*
LLVMLayer::initExceptionBlock(llvm::BasicBlock* blockException){
initExceptionsSupport();
PointerType* tyInt8P = PointerType::getInt8PtrTy(llvm::getGlobalContext());
Value* nullInt8P = llvm::ConstantPointerNull::get(tyInt8P);
builder.SetInsertPoint(blockException);
llvm::Function* fAllocate = module->getFunction("__cxa_allocate_exception");
llvm::Function* fThrow = module->getFunction("__cxa_throw");
auto exception = builder.CreateCall(fAllocate, ConstantInt::get(IntegerType::getInt64Ty(getGlobalContext()), 4));
vector<Value*> throwParams{exception, nullInt8P, nullInt8P};
builder.CreateCall(fThrow, ArrayRef<Value*>(throwParams));
builder.CreateUnreachable();
return blockException;
}
void
LLVMLayer::moveToGarbage(void *o)
{
__garbage.push_back(o);
}
llvm::Type*
LLVMLayer::
toLLVMType(const ExpandedType& ty) const {
std::map<int, llvm::StructType*> empty;
return toLLVMType(ty, empty);
}
llvm::Type*
LLVMLayer::
toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const
{
TypeAnnotation t = ty;
switch (t.__operator)
{
case TypeOperator::ARRAY:
{
assert(t.__operands.size()==1);
TypeAnnotation elTy = t.__operands.at(0);
return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
}
case TypeOperator::STRUCT:
case TypeOperator::TUPLE:
{
assert(t.__operands.size());
std::vector<llvm::Type*> pack_;
pack_.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
[this, &conjuctions](const TypeAnnotation& t){
return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
});
llvm::ArrayRef<llvm::Type*> pack(pack_);
//process recursive types:
if (conjuctions.count(t.conjuctionId)) {
auto result = conjuctions[t.conjuctionId];
result->setBody(pack, false);
return result;
}
return llvm::StructType::get(llvm::getGlobalContext(), pack, false);
};
case TypeOperator::LINK: {
llvm::StructType* conjuction = llvm::StructType::create(llvm::getGlobalContext());
int id = t.conjuctionId;
conjuctions.emplace(id, conjuction);
return conjuction;
};
case TypeOperator::CALL:
{
assert(false);
};
case TypeOperator::CUSTOM:
{
//Look in extern types
clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
return layerExtern->toLLVMType(qt);
};
case TypeOperator::NONE: {
switch (t.__value) {
case TypePrimitive::Bool:
return llvm::Type::getInt1Ty(llvm::getGlobalContext());
case TypePrimitive::I32:
case TypePrimitive::Int:
case TypePrimitive::Num:
return llvm::Type::getInt32Ty(llvm::getGlobalContext());
case TypePrimitive::I8:
return llvm::Type::getInt8Ty(llvm::getGlobalContext());
case TypePrimitive::Float:
return llvm::Type::getDoubleTy(llvm::getGlobalContext());
case TypePrimitive::String:
return llvm::Type::getInt8PtrTy(llvm::getGlobalContext());
default:
assert(false);
}
}
default:
assert(false);
}
assert(false);
return nullptr;
}
void
LLVMLayer::initExceptionsSupport(){
Type* typInt8Ptr = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
if (!module->getFunction("__cxa_throw")) {
std::vector<Type*> fThrowSignature{typInt8Ptr, typInt8Ptr, typInt8Ptr};
FunctionType* tyFThrow = FunctionType::get(
/*Result=*/Type::getVoidTy(module->getContext()),
/*Params=*/fThrowSignature,
/*isVarArg=*/false);
llvm::Function::Create(
/*Type=*/tyFThrow,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"__cxa_throw", module); // (external, no body)
}
if (!module->getFunction("__cxa_allocate_exception")) {
std::vector<Type*>fAllocateSignature{IntegerType::get(module->getContext(), 64)};
FunctionType* tyFAllocate = FunctionType::get(
/*Result=*/typInt8Ptr,
/*Params=*/fAllocateSignature,
/*isVarArg=*/false);
llvm::Function::Create(
/*Type=*/tyFAllocate,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"__cxa_allocate_exception", module); // (external, no body)
}
}
bool TypeUtils::isStruct(const ExpandedType& ty){
const TypeAnnotation& t = ty.get();
if (t.__operator==TypeOperator::STRUCT) {
return true;
}
if (t.__operator != TypeOperator::CUSTOM) {
return false;
}
clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
const clang::Type * raw = tqual.getTypePtr();
// TODO skip ALL the pointers until non-pointer type found
if (raw->isStructureType()) return true;
if (!raw->isAnyPointerType()) return false;
- const clang::PointerType* tPtr = raw->getAs<clang::PointerType>();
clang::QualType pointee = raw->getPointeeType();
- const clang::Type * pointeeRaw = pointee.getTypePtr();
return pointee->isStructureType();
}
bool TypeUtils::isPointer(const ExpandedType &ty) {
if (ty.get().__operator != TypeOperator::CUSTOM) return false;
clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
return llvm->layerExtern->isPointer(qt);
}
std::vector<std::string>
TypeUtils::getStructFields(const ExpandedType &t) {
return (t.get().__operator == TypeOperator::STRUCT)
? t.get().fields
: llvm->layerExtern->getStructFields(
llvm->layerExtern->lookupType(t.get().__valueCustom));
}
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index 8ca4dc2..7eac8f0 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,15 +1,36 @@
#include "abstractpass.h"
#include "attachments.h"
#include "passmanager.h"
using namespace std;
namespace xreate {
+ template<>
+ void defaultValue(){};
+
void AbstractPassBase::finish()
{}
AbstractPassBase::AbstractPassBase(PassManager *manager)
: man(manager) {
}
+
+ template<>
+ void
+ AbstractPass<void>::processSymbol(const std::string& ident, PassContext context)
+ {
+ const Symbol& symbol = context.scope->findSymbol(ident);
+
+ if (__visitedSymbols.isCached(symbol))
+ return;
+
+ if (CodeScope::hasDeclaration(symbol)) {
+ __visitedSymbols.setCachedValue(symbol);
+
+ PassContext context2 = context;
+ context2.scope = symbol.scope;
+ process(CodeScope::findDeclaration(symbol), context2, ident);
+ }
+ }
}
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index da48e1c..81667b4 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,123 +1,169 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
#include "passmanager.h"
#include<iostream>
using namespace std;
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
PassContext&& updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return std::move(context2);
}
~PassContext(){}
};
class PassManager;
class AbstractPassBase {
public:
AbstractPassBase(PassManager* manager);
virtual void run()=0;
virtual void finish();
PassManager* man;
};
+ template<class Output>
+ Output defaultValue();
+
+ template<class Output>
+ class SymbolCache: private std::map<Symbol, Output>{
+ public:
+ bool isCached(const Symbol& symbol){
+ return this->count(symbol);
+ }
+
+ Output setCachedValue(const Symbol& symbol, Output&& value){
+ this->emplace(symbol, value);
+ return value;
+ }
+
+ Output getCachedValue(const Symbol& symbol){
+ assert(this->count(symbol));
+ return this->at(symbol);
+ }
+ };
+
+ template<>
+ class SymbolCache<void>: private std::set<Symbol>{
+ public:
+ bool isCached(const Symbol& symbol){
+ bool result = this->count(symbol) > 0;
+ return result;
+ }
+ void setCachedValue(const Symbol& symbol){
+ this->insert(symbol);
+ }
+
+ void getCachedValue(const Symbol& symbol){
+ }
+ };
+
template<class Output>
class AbstractPass: public AbstractPassBase {
private:
- std::set<Symbol> __visitedSymbols;
- Output __defaultValue;
+ SymbolCache<Output> __visitedSymbols;
+
+ Output processSymbol(const std::string& ident, PassContext context){
+ const Symbol& symbol = context.scope->findSymbol(ident);
+
+ if (__visitedSymbols.isCached(symbol))
+ return __visitedSymbols.getCachedValue(symbol);
+ if (CodeScope::hasDeclaration(symbol)) {
+ PassContext context2 = context;
+ context2.scope = symbol.scope;
+ Output&& result = process(CodeScope::findDeclaration(symbol), context2, ident);
+ return __visitedSymbols.setCachedValue(symbol, std::move(result));
+ }
+
+ return defaultValue<Output>();
+ }
public:
- AbstractPass(PassManager* manager, Output defaultValue=Output())
- : AbstractPassBase(manager), __defaultValue(defaultValue) {}
+ AbstractPass(PassManager* manager)
+ : AbstractPassBase(manager){}
//NOTE implement processFnCall
virtual void processFnCall(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 process(scope->__body, context);
}
virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
switch (expression.__state) {
case Expression::COMPOUND:
- assert(expression.op != Operator::MAP || expression.op == Operator::MAP && expression.blocks.size());
+ assert(expression.op != Operator::MAP || (expression.op == Operator::MAP && expression.blocks.size()));
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL) {
const std::string &calleeName = expression.getValueString();
ManagedFnPtr callee = man->root->findFunction(calleeName);
if (callee) processFnCall(callee, context);
}
break;
case Expression::IDENT:
assert(context.scope);
+ return processSymbol(expression.getValueString(), context);
- std::string ident = expression.getValueString();
- const Symbol& symbol = context.scope->findSymbol(ident);
-
- if (__visitedSymbols.count(symbol)) {assert(false && "Invalid state");}
- __visitedSymbols.insert(symbol);
-
- PassContext context2 = context;
- context2.scope = symbol.scope;
- if (CodeScope::hasDeclaration(symbol)) {
- return process(CodeScope::findDeclaration(symbol), context2, ident);
- }
-
- break;
+ default:
+ break;
}
+
+ return defaultValue<Output>();
}
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while (rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while (f.isValid()) {
process(f);
++f;
}
}
};
+
+ template<>
+ void
+ AbstractPass<void>::processSymbol(const std::string& ident, PassContext context);
}
#endif
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index ed0d8b2..0fde4db 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,454 +1,457 @@
#include "compilepass.h"
#include "clasplayer.h"
#include <ast.h>
#include <iostream>
#include "query/containers.h"
#include "instructions/instr-containers.h"
#include "ExternLayer.h"
using namespace std;
using namespace xreate;
using namespace llvm;
CompilePass::CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
: scope(codeScope), pass(compilePass), function(f)
{}
void
CompilePass::CodeScopeUnit::bindArg(llvm::Value* var, std::string&& name)
{
assert(scope->__vartable.count(name));
VID id = scope->__vartable.at(name);
__rawVars[id] = var;
}
llvm::Value*
CompilePass::CodeScopeUnit::convertType(llvm::Value* source, llvm::Type* tyTarget){
LLVMLayer* llvm = pass->man->llvm;
if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
{
llvm::IntegerType* tyTargetInt = llvm::dyn_cast<IntegerType>(tyTarget);
llvm::IntegerType* tySourceInt = llvm::dyn_cast<IntegerType>(source->getType());
if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
return llvm->builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
}
if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
return llvm->builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
}
}
assert(false && "no automatic type conversion possible");
}
llvm::Value*
CompilePass::CodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
#define VARNAME(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left; llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
CompilePass::Context context{function, this, pass};
containers::Instructions instructions = containers::Instructions(context);
switch (expr.op) {
case Operator::ADD:
case Operator::SUB:
case Operator::MUL:
case Operator::DIV:
case Operator::EQU:
case Operator::LSS:
case Operator::GTR:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = process(expr.operands[0]);
right = process(expr.operands[1]);
if (left->getType()!= right->getType()) {
right = convertType(right, left->getType());
}
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
return l.builder.CreateAdd(left, right, VARNAME("tmp_add"));
break;
case Operator::SUB:
return l.builder.CreateSub(left, right, VARNAME("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, VARNAME("tmp_mul"));
break;
case Operator::DIV:
return l.builder.CreateSDiv(left, right, VARNAME("tmp_div"));
break;
case Operator::EQU:
left->dump();
right->dump();
return l.builder.CreateICmpEQ(left, right, VARNAME("tmp_equ"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, VARNAME("tmp_lss"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, VARNAME("tmp_gtr"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
return l.builder.CreateNeg(left, VARNAME("tmp_neg"));
break;
case Operator::CALL: {
assert(expr.__state == Expression::COMPOUND);
std::string fname = expr.getValueString();
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression &operand) {
return process(operand);
}
);
FunctionUnit* calleeUnit = pass->getFunctionUnit(string(fname));
// external function
if (!calleeUnit) {
llvm::Function* external = pass->man->llvm->layerExtern->lookupFunction(fname);
return l.builder.CreateCall(external, args, hintVarDecl);
}
if (calleeUnit->isInline()) {
return calleeUnit->compileInline(move(args), this->function);
}
llvm::BasicBlock* blockPrev = pass->man->llvm->builder.GetInsertBlock();
llvm::Value* callee = calleeUnit->compile();
pass->man->llvm->builder.SetInsertPoint(blockPrev);
return l.builder.CreateCall(callee, args, hintVarDecl);
}
case Operator::IF:
{
return instructions.compileIf(expr, hintVarDecl);
}
case Operator::SWITCH:
{
return nullptr; //instructions.compileSwitch();
}
case Operator::LIST:
{
return instructions.compileConstantArray(expr, hintVarDecl);
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::LIST_NAMED:
{
typedef Expanded<TypeAnnotation> ExpandedType;
ExpandedType tyRaw = l.ast->expandType(expr.type);
const std::vector<string> fields = (tyRaw.get().__operator == TypeOperator::CUSTOM)?
l.layerExtern->getStructFields(l.layerExtern->lookupType(tyRaw.get().__valueCustom))
: tyRaw.get().fields;
std::map<std::string, size_t> indexFields;
for(size_t i=0, size = fields.size(); i<size; ++i){
indexFields.emplace(fields[i], i);
}
llvm::StructType* tyRecord = llvm::cast<llvm::StructType>(l.toLLVMType(tyRaw));
llvm::Value* record = llvm::UndefValue::get(tyRecord);
- for (int i=0; i<expr.operands.size(); ++i){
+ for (size_t i=0; i<expr.operands.size(); ++i){
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = 0;
if (operand.isNone()){
llvm::Type* tyNullField = tyRecord->getElementType(fieldId);
result = llvm::UndefValue::get(tyNullField);
} else {
result = process(operand);
}
assert (result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolid(expr, VARNAME("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, VARNAME("fold"));
};
case Operator::INDEX:
{
//TODO allow multiindex
assert(expr.operands.size()==1);
const std::string &ident = expr.getValueString();
Symbol s = scope->findSymbol(ident);
const TypeAnnotation& t = s.scope->findDefinition(s);
const ExpandedType& t2 = pass->man->root->expandType(t);
switch (t2.get().__operator)
{
case TypeOperator::STRUCT: case TypeOperator::CUSTOM:
{
Expression idx = expr.operands.at(0);
assert(idx.__state == Expression::STRING);
std::string idxField = idx.getValueString();
llvm::Value* aggr = compileSymbol(s, ident);
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::ARRAY: {
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this] (const Expression& op){return process(op);}
);
return instructions.compileArrayIndex(s, indexes, VARNAME(string("el_") + ident));
};
default:
assert(false);
}
};
case Operator::NONE:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT: {
const std::string &ident = expr.getValueString();
Symbol s = scope->findSymbol(ident);
return compileSymbol(s, ident);
}
case Expression::NUMBER: {
int literal = expr.getValueDouble();
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
}
case Expression::STRING: {
return instructions.compileConstantStringAsPChar(expr.getValueString(), hintVarDecl);
};
-
+ default: {
+ break;
+ }
};
break;
+ default: break;
+
}
assert(false);
return 0;
}
llvm::Value*
CompilePass::CodeScopeUnit::compile(const std::string& hintBlockDecl){
if (raw != nullptr) return raw;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
raw = process(scope->__body);
return raw;
}
llvm::Value*
CompilePass::CodeScopeUnit::compileSymbol(const Symbol& s, std::string hintRetVar)
{
CodeScope* scope = s.scope;
CodeScopeUnit* self = function->getScopeUnit(scope);
if (self->__rawVars.count(s.identifier)) {
return self->__rawVars[s.identifier];
}
return self->__rawVars[s.identifier] = self->process(scope->findDeclaration(s), hintRetVar);
}
bool
CompilePass::FunctionUnit::isInline(){
Symbol ret = Symbol{0, function->__entry};
bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
return flagOnTheFly;
}
llvm::Function*
CompilePass::FunctionUnit::compile(){
if (raw != nullptr) return raw;
std::vector<llvm::Type *> types;
LLVMLayer* llvm = pass->man->llvm;
CodeScope* entry = function->__entry;
std::transform(entry->__args.begin(), entry->__args.end(), std::inserter(types, types.end()),
[this, llvm, entry](const std::string &arg)->llvm::Type* {
assert(entry->__vartable.count(arg));
VID argid = entry->__vartable.at(arg);
assert(entry->__definitions.count(argid));
return llvm->toLLVMType(pass->man->root->expandType(entry->__definitions.at(argid)));
});
llvm::FunctionType *ft = llvm::FunctionType::get(llvm->toLLVMType(pass->man->root->expandType(entry->__definitions[0])), types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(function->__name, ft));
CodeScopeUnit* entryCompilation = getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = raw->arg_begin();
for (std::string &arg : entry->__args) {
VID argid = entry->__vartable[arg];
entryCompilation->__rawVars[argid] = fargsI;
fargsI->setName(arg);
++fargsI;
}
const std::string blockName = "entry";
llvm->builder.CreateRet(entryCompilation->compile(blockName));
llvm->moveToGarbage(ft);
return raw;
}
-//TEST FunctionUnit::compileInline
llvm::Value*
CompilePass::FunctionUnit::compileInline(std::vector<llvm::Value *> &&args, CompilePass::FunctionUnit* outer){
CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
for(int i=0, size = args.size(); i<size; ++i) {
entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__args.at(i)));
}
return entryCompilation->compile();
}
CompilePass::CodeScopeUnit*
CompilePass::FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
scopes.emplace(scope, std::unique_ptr<CodeScopeUnit>(unit));
}
return scopes.at(scope).get();
}
CompilePass::CodeScopeUnit*
CompilePass::FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
CompilePass::CodeScopeUnit*
CompilePass::FunctionUnit::getScopeUnit(ManagedScpPtr scope){
return getScopeUnit(&*scope);
}
CompilePass::FunctionUnit*
CompilePass::getFunctionUnit(const CompilePass::FunctionQuery& f){
ManagedFnPtr fkey = man->root->findFunction(f.name);
//external functions:
if (!fkey){
return nullptr;
}
if (!functions.count(&*fkey)){
functions.emplace(&*fkey, std::unique_ptr<FunctionUnit>(new FunctionUnit(fkey, this)));
}
return functions.at(&*fkey).get();
}
void
CompilePass::run(){
//Find out main function;
- ClaspLayer::ModelRange model = man->clasp->query(Config::get("function-entry"));
+ ClaspLayer::ModelFragment model = man->clasp->query(Config::get("function-entry"));
assert(model && "Error: No entry function found");
assert(model->first != model->second && "Error: Ambiguous entry function");
string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model->first->second));
FunctionUnit* unitMain = getFunctionUnit(move(nameMain));
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction(){
assert(entry);
return entry;
}
//CODESCOPE COMPILATION PHASE
//FIND SYMBOL(compilation phase):
//if (!forceCompile)
//{
// return result;
//}
// //search in already compiled vars
//if (__rawVars.count(vId))
//{
// return result;
//}
//if (!__declarations.count(vId)) {
// //error: symbol is uncompiled scope arg
// assert(false);
//}
//const Expression& e = __declarations.at(vId);
//__rawVars[vId] = process(e, l, name);
//FIND FUNCTION
//llvm::Function*
//CompilePass::findFunction(const std::string& name){
// ManagedFnPtr calleeFunc = man->root->findFunction(name);
// assert(calleeFunc.isValid());
// return nullptr;
//}
diff --git a/cpp/src/pass/dfgpass.cpp b/cpp/src/pass/dfgpass.cpp
index 197541f..5520d2f 100644
--- a/cpp/src/pass/dfgpass.cpp
+++ b/cpp/src/pass/dfgpass.cpp
@@ -1,184 +1,187 @@
#include "dfgpass.h"
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
-using namespace xreate;
using namespace std;
+namespace xreate{
DFGPass::DFGPass(PassManager* manager)
: AbstractPass(manager), clasp(man->clasp)
{}
SymbolNode
DFGPass::process(ManagedFnPtr function){
SymbolNode symbolRet = AbstractPass::process(function);
if (SymbolPacked* symbolRetPacked = boost::get<SymbolPacked>(&symbolRet)){
Expression retExpr(Operator::CALL, {Atom<Identifier_t>(Config::get("clasp.ret.symbol")),
Atom<Identifier_t>(boost::str(boost::format("(%1%, %2%)")
%(symbolRetPacked->identifier)
% (symbolRetPacked->scope)))
});
const std::vector<Tag> tag{{retExpr, TagModifier::NONE}};
clasp->cfagraph.addFunctionNodeTags(function->getName(), tag);
} else if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
std::vector<Tag> tags;
tags.reserve(symbT->tags.size());
const std::string stmntRetTag = Config::get("clasp.ret.tag");
std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
[&stmntRetTag](const Expression& e) {
Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
return Tag{e, TagModifier::NONE};
});
clasp->cfagraph.addFunctionNodeTags(function->getName(), tags);
}
+
+ return SymbolInvalid();
}
SymbolNode
DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
// write down adhoc expression tags:
if (expression.tags.size() && decl.length()) {
for (pair<std::string, Expression> tag: expression.tags) {
- SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), decl);
+ SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
__context.graph.addTag(nodeThis, Expression(tag.second));
}
}
switch(expression.__state) {
- case Expression::IDENT:
+ case Expression::IDENT: {
const string& ident = expression.getValueString();
SymbolNode nodeFrom = AbstractPass::process(expression, context, decl);
- SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident));
+ SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident), context.function->getName() + ":" + ident);
__context.graph.addLink(nodeTo, nodeFrom, DFGConnection::ALIAS);
return nodeTo;
+ }
+
+ default: break;
}
//special case for NONE value:
if (expression.isNone()){
return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
}
switch(expression.op) {
case Operator::CALL: {
const string &name = expression.getValueString();
std::vector<SymbolNode> operands;
operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
ManagedFnPtr function = man->root->findFunction(name);
if (!function) return SymbolInvalid();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
- std::vector<SymbolNode>::iterator op = operands.begin();
- for (const std::string &arg: scopeRemote->__args) {
- const Symbol &nodeRemote = scopeRemote->findSymbol(arg);
-
- SymbolPacked* operandPacked = boost::get<SymbolPacked>(&*op);
- assert(operandPacked);
- __context.graph.addLink(clasp->pack(nodeRemote), *operandPacked, DFGConnection::OPT);
- ++op;
+ std::vector<SymbolNode>::iterator nodeActual = operands.begin();
+ for (const std::string &identFormal: scopeRemote->__args) {
+ const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
+ __context.graph.addLink(clasp->pack(symbolFormal, name + ":" + identFormal), *nodeActual, DFGConnection::OPT);
+ ++nodeActual;
}
//TODO need SymbolTransient::connection mark in order to represent OPT connection
- return clasp->pack(Symbol{0, scopeRemote});
+ return clasp->pack(Symbol{0, scopeRemote}, name + ": *retv");
}
+
+ default: break;
}
- std::vector<SymbolNode> operands;
+
+
+ SymbolNode result = AbstractPass::process(expression, context, decl);
if (expression.__state != Expression::COMPOUND){
- AbstractPass::process(expression, context, decl);
- return SymbolInvalid();
+ return result;
}
+ std::vector<SymbolNode> operands;
if (__signatures.count(expression.op)) {
const Expression &scheme = __signatures.at(expression.op);
operands.reserve(expression.getOperands().size());
if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
string caption = expression.getValueString();
operands.push_back(process(Expression(move(caption)), context, ""));
}
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
std::vector<SymbolNode>::iterator arg = operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
__context.graph.addTag(*arg, Expression(*tag));
}
++arg; ++tag;
}
Expression retTag = *scheme.getOperands().begin();
if (retTag.__state != Expression::INVALID) {
- return SymbolTransient{{retTag}};
+ __context.graph.addTag(result, move(retTag));
}
}
- // adhoc for MAP case, TODO reorganize code in more clear manner
- if (expression.op == Operator::MAP) {
+ // adhoc for MAP case, TODO reorganize code in more clear manner
+ if (expression.op == Operator::MAP) {
SymbolNode nodeFrom;
- if (operands.size()) {
- nodeFrom = operands.at(0);
- } else {
- nodeFrom = process(expression.getOperands().at(0), context);
- }
+ if (operands.size()) {
+ nodeFrom = operands.at(0);
+ } else {
+ nodeFrom = process(expression.getOperands().at(0), context);
+ }
- assert(!decl.empty());
- SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl));
+ assert(!decl.empty());
+ SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
assert(nodeFromPacked);
__context.graph.addLink(move(nodeTo), *nodeFromPacked, DFGConnection::PROTO);
- }
-
- if (__signatures.count(expression.op) || expression.op == Operator::MAP) {
- for (CodeScope* scope: expression.blocks) {
- AbstractPass::process(scope, context);
- }
-
- return SymbolInvalid();
- }
+ }
- return SymbolInvalid();
+ return result;
}
void
DFGPass::run()
{
init();
return AbstractPass::run();
}
void
DFGPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
__signatures.emplace(scheme.op, scheme);
}
}
void DFGPass::finish()
{
man->clasp->addDFAData(move(__context.graph));
}
+
+template<>
+SymbolNode defaultValue(){return SymbolInvalid();};
+
+}
diff --git a/cpp/src/pass/environmenttestspass.cpp b/cpp/src/pass/environmenttestspass.cpp
new file mode 100644
index 0000000..bac56b7
--- /dev/null
+++ b/cpp/src/pass/environmenttestspass.cpp
@@ -0,0 +1,30 @@
+/*
+ * environmenttestspass.cpp
+ *
+ * Created on: Nov 17, 2015
+ * Author: pgess
+ */
+
+#include <string>
+#include <list>
+
+void
+EnvironmentTestsPass::run(){
+
+ list<string> arftefacts = solver->query("depends(env())");
+
+ //check artifacts
+ for (artefact: artifacts){
+ Function funcProbe = findProberForArtefact(artefact);
+
+ result = funcProbe->run();
+ results->save(result);
+ }
+
+ for (artefact: artefacts){
+ if (results->getResult(artefact)){
+ Function funcProvider = findProviderForArtefact(artefact);
+ funcProvider->run();
+ }
+ }
+}
diff --git a/cpp/src/pass/environmenttestspass.h b/cpp/src/pass/environmenttestspass.h
new file mode 100644
index 0000000..651acda
--- /dev/null
+++ b/cpp/src/pass/environmenttestspass.h
@@ -0,0 +1,17 @@
+/*
+ * environmenttestspass.h
+ *
+ * Created on: Nov 17, 2015
+ * Author: pgess
+ */
+
+#ifndef SRC_PASS_ENVIRONMENTTESTSPASS_H_
+#define SRC_PASS_ENVIRONMENTTESTSPASS_H_
+
+
+
+class EnvironmentTestsPass {
+
+}
+
+#endif /* SRC_PASS_ENVIRONMENTTESTSPASS_H_ */
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 0881b47..662f41e 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,161 +1,163 @@
//
// Created by pgess on 3/14/15.
//
#include <clasplayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
typedef SymbolAttachments attach;
if (attach::exists<Implementation>(s))
{
return attach::get<Implementation>(s);
}
return Implementation::create(s);
}
void
Query::init(ClaspLayer* clasp)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//read all proto data
auto range = clasp->query(Config::get("containers.id.prototypes"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom) {
auto data = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0> (data));
Symbol prototype = clasp->unpack(get<1> (data));
prototypes[root] = prototype;
}
// fill implementation data for a data sources:
range = clasp->query(Config::get("containers.id.implementations"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto data = ClaspLayer::parse<SymbolPacked, string>(atom->second);
Symbol var = clasp->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
Implementation impl = Implementation::create(var);
SymbolAttachments::put<Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
//fill implementation data for a cluster roots
for (const pair<Symbol, string> & root: roots)
{
Symbol prototype = prototypes[root.first];
while (prototypes.count(prototype)) {
prototype = prototypes.at(prototype);
}
SymbolAttachments::put<Implementation>(root.first, Implementation(SymbolAttachments::get<Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
range = clasp->query(Config::get("containers.id.clusters"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto info = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0>(info));
Symbol child = clasp->unpack(get<1>(info));
if (!(child == root)) {
Implementation rootImpl = SymbolAttachments::get<Implementation>(root);
SymbolAttachments::put<Implementation>(child, move(rootImpl));
}
}
flagIsDataLoaded = true;
}
//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
Implementation
Implementation::create(const Symbol &var)
{
Expression varDecl = CodeScope::findDeclaration(var);
switch (varDecl.op)
{
case Operator::LIST_RANGE: {
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST: {
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
+
+ default: break;
};
ImplementationLinkedList ill(var);
if (ill){
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
}
Implementation
Implementation::create(const Symbol& var, const std::string& implSerialized)
{
Expression varDecl = CodeScope::findDeclaration(var);
if (implSerialized == Config::get("containers.impl.solid"))
{
return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
} else if (implSerialized == Config::get("containers.impl.onthefly")) {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}};
}
assert(false && "unable to determine proper implementation for the symbol");
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source){
const Expression& sourceExpr = CodeScope::findDeclaration(source);
if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))){
flagIsValid = true;
Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
assert(tagLinkedlist.operands.size() == 2);
fieldPointer = tagLinkedlist.operands.at(0).getValueString();
terminator = tagLinkedlist.operands.at(1);
}
}
ImplementationLinkedList:: operator bool () const{
return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/tests/CFGtests.cpp b/cpp/tests/CFGtests.cpp
index 44e92ef..cbda26a 100644
--- a/cpp/tests/CFGtests.cpp
+++ b/cpp/tests/CFGtests.cpp
@@ -1,62 +1,62 @@
/*
* testsCFG.cpp
*
* Created on: Jul 17, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "pass/dfgpass.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
TEST(CFG, 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();
- ClaspLayer::ModelRange answer = man->clasp->query("annotationF1");
+ 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);
+ EXPECT_EQ(1, countNoneValue);
}
TEST(CFG, testLoopContextExists){
PassManager* man = PassManager::prepareForCode (
"interface(cfa){\n"
" operator fold:: annotation1.\n"
"}\n"
"\n"
"main = function() :: int; entry {\n"
" x = [1..10]:: [int].\n"
" sum = loop fold (x->el:: int, 0->sum:: int):: [int] {\n"
" el + sum + f1()\n"
" }. \n"
" sum\n"
"}"
"f1 = function()::int {\n"
" x = 0:: int. "
" x\n"
"}"
);
man->runWithoutCompilation();
}
diff --git a/cpp/tests/DFGtests.cpp b/cpp/tests/DFGtests.cpp
index fd82f58..7371367 100644
--- a/cpp/tests/DFGtests.cpp
+++ b/cpp/tests/DFGtests.cpp
@@ -1,42 +1,42 @@
/*
* DFGtests.cpp
*
* Created on: Jul 23, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "pass/dfgpass.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
TEST(DFG, testFunctionRetSymbolExists){
PassManager* man = PassManager::prepareForCode
("test = function():: int; entry {\n"
" data = [1..5]::[int].\n"
" \n"
" result = loop fold(data->i::int, 0->sum::int)::int{\n"
" if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
" }.\n"
" \n"
" result\n"
"}");
man->runWithoutCompilation();
- ClaspLayer::ModelRange answer = man->clasp->query(Config::get("clasp.ret.symbol"));
+ ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.ret.symbol"));
if (answer)
EXPECT_EQ(1, std::distance(answer->first, answer->second));
for (auto functionIt = answer->first; functionIt != answer->second; ++functionIt){
auto ret = ClaspLayer::parse<string, Gringo::Value>(functionIt->second);
ASSERT_EQ("test", std::get<0>(ret));
SymbolPacked symbolRet = std::get<0>(ClaspLayer::parse<SymbolPacked>(std::get<1>(ret)));
ASSERT_EQ(3, symbolRet.identifier);
ASSERT_EQ(0, symbolRet.scope);
}
}
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index 2929080..7c4de20 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,41 +1,49 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(AST, Containers1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
const AST& ast = parser.root;
fclose(input);
}
-TEST(AST, CFAData) {
+TEST(AST, InterfacesDataCFA) {
PassManager* man = PassManager::prepareForCode
("interface(cfa){\n"
" operator map :: annotation1.\n"
"}");
auto answer = man->root->__interfacesData.equal_range(CFA);
EXPECT_EQ(1, std::distance(answer.first, answer.second));
Expression&& scheme = move(answer.first->second);
EXPECT_EQ(Operator::MAP, scheme.op);
EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString());
}
+TEST(AST, DISABLED_InterfacesDataDFA){
+
+}
+
+TEST(AST, DISABLED_InterfacesDataExtern){
+
+}
+
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
new file mode 100644
index 0000000..c305e3e
--- /dev/null
+++ b/cpp/tests/compilation.cpp
@@ -0,0 +1,5 @@
+#include "gtest/gtest.h"
+
+//TEST FunctionUnit::compileInline
+TEST(Compilation, DISABLED_functionInline1){
+}
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 4c149bc..611ccfe 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,57 +1,54 @@
/*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Parser.h"
#include "query/containers.h"
using namespace std;
using namespace xreate;
using namespace containers;
-TEST(Containers, DISABLED_DFAData1){
-}
-
TEST(Containers, ContanierLinkedList1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symb_chilrenRaw = body->findSymbol("childrenRaw");
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/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
std::unique_ptr<PassManager> program(PassManager::prepareForCode(scanner));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
ASSERT_EQ(16, answer);
fclose(input);
}
diff --git a/cpp/tests/diagnostic-messages.cpp b/cpp/tests/diagnostic-messages.cpp
new file mode 100644
index 0000000..b46cdf0
--- /dev/null
+++ b/cpp/tests/diagnostic-messages.cpp
@@ -0,0 +1,28 @@
+/*
+ * diagnostic-messages.cpp
+ *
+ * Created on: Oct 27, 2015
+ * Author: pgess
+ */
+
+#include "gtest/gtest.h"
+
+using namespace std;
+
+TEST(Diagnostic_DFA, DISABLED_recursion1){
+
+ //Error while processing recursion, Should be some diagnostic complaints
+ std::string code = \
+ "test1 = function()::[int] {\n"
+ " varRecursion = loop map(varRecursion->el:: int)::[int]{\n"
+ " el\n"
+ " }.\n"
+ " \n"
+ " varRecursion\n"
+ "}";
+
+ PassManager* man = PassManager::prepareForCode(code);
+ DFGPass* pass = new DFGPass(man);
+ pass->run();
+ pass->finish();
+}
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
index ae6287a..ba12e3c 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,104 +1,104 @@
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
TEST(InterfaceExternC, testAST){
std::string code = " \
interface(extern-c){ \
xml2 = library:: pkgconfig(\"libxml-2.0\"). \
\
include { \
xml2 = [\"libxml/tree.h\"] \
}. \
} \
";
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(1, parser.root.__externdata.size());
for (const ExternEntry& lib: parser.root.__externdata){
ASSERT_EQ("libxml-2.0", lib.package);
ASSERT_EQ(1, lib.headers.size());
ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
}
}
TEST(InterfaceExternC, testfetchPackageHeaders){
ExternEntry entry{"libxml-2.0", {}};
vector<string> args = ExternLayer::fetchPackageFlags(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
}
TEST(InterfaceExternC, testfetchPackageLibs){
ExternEntry entry{"libxml-2.0", {}};
vector<string> args = ExternLayer::fetchPackageLibs(entry);
ASSERT_EQ(1, args.size());
- ASSERT_EQ("-lxml2", args.at(0));
+ ASSERT_EQ("xml2", args.at(0));
}
TEST(InterfaceExternC, testLoadLib){
std::string msgErr;
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)){
cout << msgErr;
ASSERT_EQ("", msgErr);
}
ASSERT_TRUE(true);
}
TEST(InterfaceExternC, testBSD1){
std::string code = " \n\
interface(extern-c){ \n\
libbsd = library:: pkgconfig(\"libbsd\"). \n\
\n\
include { \n\
libbsd = [\"bsd/stdlib.h\"] \n\
}. \n\
}\n"
"main= function():: int; entry{arc4random() }";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = 24;
answer = entry();
cout << answer;
ASSERT_NE(24, answer);
}
TEST(InterfaceExternC, testStructFields1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symbTree = body->findSymbol("tree");
const TypeAnnotation& tTree = CodeScope::findDefinition(symbTree);
const 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/pointers.cpp b/cpp/tests/pointers.cpp
new file mode 100644
index 0000000..e2e05a9
--- /dev/null
+++ b/cpp/tests/pointers.cpp
@@ -0,0 +1,9 @@
+#include "gtest/gtest.h"
+
+TEST(Pointers, DISABLED_validptr1){
+
+}
+
+TEST(Pointers, DISABLED_localscopeptr1){
+
+}
diff --git a/cpp/tests/safety.cpp b/cpp/tests/safety.cpp
index 2af6879..e69de29 100644
--- a/cpp/tests/safety.cpp
+++ b/cpp/tests/safety.cpp
@@ -1,9 +0,0 @@
-#include "gtest/gtest.h"
-
-/**
- * Safety checks:
- * (*) valid ptr (not null)
- */
-TEST(Safety, validptr1){
-
-}
diff --git a/cpp/tests/skipdetection.cpp b/cpp/tests/skipdetection.cpp
index 5ccb14b..c1ba1a2 100644
--- a/cpp/tests/skipdetection.cpp
+++ b/cpp/tests/skipdetection.cpp
@@ -1,32 +1,32 @@
/*
* skipdetection.cpp
*
* Created on: Jul 10, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "clasplayer.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
TEST(SkipDetection, testNoneValueTagExists){
PassManager* man = PassManager::prepareForCode
("test = function():: int; entry {\n"
" data = [1..5]::[int].\n"
" \n"
" result = loop fold(data->i::int, 0->sum::int)::int{\n"
" if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
" }.\n"
" \n"
" result\n"
"}");
man->runWithoutCompilation();
- ClaspLayer::ModelRange answer = man->clasp->query(Config::get("clasp.nonevalue"));
+ ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.nonevalue"));
int countNoneValue = 0;
if (answer)
countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
}
diff --git a/cpp/tests/testBasic.cpp b/cpp/tests/testBasic.cpp
index 9cb9a5c..1f1acb5 100644
--- a/cpp/tests/testBasic.cpp
+++ b/cpp/tests/testBasic.cpp
@@ -1,26 +1,26 @@
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
using namespace xreate;
-TEST(EntryFunction, test1){
+TEST(Basic, functionEntry1){
std::unique_ptr<PassManager> program(PassManager::prepareForCode(
"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);
}
diff --git a/cpp/tests/testClangAPI.cpp b/cpp/tests/testClangAPI.cpp
index 15bcd61..0005ad2 100644
--- a/cpp/tests/testClangAPI.cpp
+++ b/cpp/tests/testClangAPI.cpp
@@ -1,190 +1,190 @@
//
// Created by pgess on 4/16/15.
//
#include "gtest/gtest.h"
#include <llvm/IR/DerivedTypes.h>
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenTypes.h"
#include "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenModule.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "llvm/IR/LLVMContext.h"
#include "clang/Basic/TargetInfo.h"
#include <boost/format.hpp>
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
/*
class PrintFunctionsConsumer : public ASTConsumer {
public:
bool HandleTopLevelDecl(DeclGroupRef DG) override {
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
const Decl *D = *i;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
return true;
}
};
class PFAction : public ASTFrontendAction {
public:
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return llvm::make_unique<PrintFunctionsConsumer>();
}
};
*/
class PrinterType : public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
ASTContext* C = Result.Context;
llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
QualType Ty = decl->getUnderlyingType();
llvm::errs() << "<" << Ty.getAsString() << ">" ;
CodeGenOptions *CGO = new CodeGenOptions;
const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
rawTy->dump();
results.push_back(rawTy);
}
}
std::vector<llvm::Type*> results;
};
class PrinterFunction: public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
QualType Ty = decl->getType();
llvm::errs() << "<" << Ty.getAsString() << ">" ;
ASTContext* C = Result.Context;
llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
CodeGenOptions *CGO = new CodeGenOptions;
const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
//const clang::FunctionType* Ty = decl->getType()->getAs<clang::FunctionType>();
llvm::FunctionType* rawFuncTy = llvm::dyn_cast<llvm::FunctionType>(rawTy);
rawFuncTy->dump();
results.push_back(rawFuncTy);
/*
llvm::Function* fDeclaration = llvm::Function::Create(rawFuncTy, llvm::GlobalValue::ExternalLinkage, "xxxx", M);
fDeclaration->dump();
*/
}
}
std::vector<llvm::Type*> results;
};
//DEBT fix dependency on clasp/gcc version
vector<string> argv = {
"-I/usr/include/libxml2"
,"-I/usr/local/include"
,"-I/usr/lib/llvm-3.6/lib/clang/3.6.0/include"
,"-I/usr/include"
};
TEST(ClangAPI, testExternalType)
{
//,, "-I/usr/include/linux"
// "-cc1", "-emit-pch", "-disable-free", "-disable-llvm-verifier", "-mrelocation-model", "static",
// "-mthread-model", "posix", "-mdisable-fp-elim", "-fmath-errno", "-masm-verbose",
// "-mconstructor-aliases", "-munwind-tables", "-fuse-init-array", "-target-cpu", "x86-64", "-target-linker-version", "2.25",
//"-dwarf-column-info", "-resource-dir", "/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0",
//"clang", "--",
/*
int argc= argv.size();
llvm::cl::OptionCategory cat("aaaa");
LLVMInitializeNativeTarget();
CommonOptionsParser op(argc, &*(argv.begin()), cat);
ClangTool tool(op.getCompilations(), op.getSourcePathList());
*/
auto matcherType =
typedefDecl(hasName("xmlNodePtr")).bind("typename");
MatchFinder finder;
PrinterType printer;
finder.addMatcher(matcherType, &printer);
std::string code = (boost::format("#include \"%1%\"") % ("libxml/tree.h")).str();
//runToolOnCodeWithArgs(newFrontendActionFactory(&finder).get()->create(), code, argv);
std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
ASTContext & context = ast->getASTContext();
finder.matchAST(context);
- string signatureExpected = "%struct._xmlNode.0*";
+ string signatureExpected = "%struct._xmlNode*";
ASSERT_EQ(1, printer.results.size());
llvm::Type* tyActual = printer.results.at(0);
string strActual;
llvm::raw_string_ostream ss(strActual);
tyActual->print(ss);
ASSERT_EQ(signatureExpected, ss.str());
//int x = tool.run(newFrontendActionFactory(&finder).get());
}
TEST(ClangAPI, testExternalFunction){
auto matcherType = functionDecl(hasName("arc4random")).bind("function");
MatchFinder finder;
PrinterFunction printer;
finder.addMatcher(matcherType, &printer);
std::string code = (boost::format("#include \"%1%\"") % ("bsd/stdlib.h")).str();
std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
ASTContext & context = ast->getASTContext();
finder.matchAST(context);
string signatureExpected = "i32 ()";
ASSERT_EQ(1, printer.results.size());
llvm::Type* tyActual = printer.results.at(0);
string strActual;
llvm::raw_string_ostream ss(strActual);
tyActual->print(ss);
ASSERT_EQ(signatureExpected, ss.str());
}
diff --git a/cpp/tests/testLibXml2.cpp b/cpp/tests/testLibXml2.cpp
index ada2404..a095373 100644
--- a/cpp/tests/testLibXml2.cpp
+++ b/cpp/tests/testLibXml2.cpp
@@ -1,37 +1,36 @@
//
// Created by pgess on 3/28/15.
//
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <gtest/gtest.h>
using namespace std;
TEST(libxml2, ReadXML)
{
- char* docname = "project/documentation.fodt" ;
+ char* docname = "project/documentation.fodt";
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname);
if (doc == NULL ) {
fprintf(stderr,"Document not parsed successfully. \n");
return;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return;
}
cur = cur->xmlChildrenNode;
int count =0;
while (cur != NULL) {
printf("child: %s\n", cur->name);
-
cur = cur->next;
count ++;
}
ASSERT_EQ(17, count);
}
diff --git a/cpp/tests/tests.cpp b/cpp/tests/tests.cpp
index d0e8410..66078a2 100644
--- a/cpp/tests/tests.cpp
+++ b/cpp/tests/tests.cpp
@@ -1,135 +1,136 @@
#include "utils.h"
#include <gtest/gtest.h>
using namespace std;
using namespace xreate;
int main(int argc, char **argv) {
testing::GTEST_FLAG(color) = "yes";
string testsTemplate = Config::get("tests.template");
string testsFilter = Config::get(string("tests.templates.") + testsTemplate);
testing::GTEST_FLAG(filter) = testsFilter;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+//TODO adopt useful tests
//void testParser_1()
//{
// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
// shared_ptr<Parser> parser(new Parser(scanner.get()));
// parser->Parse();
// flush(cout);
// AST& root = parser->root;
// LLVMLayer l(&root);
// root.compile(l);
// root.run(l);
//}
//void testClasp2()
//{
// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
// shared_ptr<Parser> parser(new Parser(scanner.get()));
// parser->Parse();
// flush(cout);
// if (parser->errors->count)
// {
// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
// exit(1);
// }
// AST& root = parser->root;
// ClaspLayer clasp;
// /*
// FunctionTagsPass(root).run(clasp);
// RulesPass(root).run(clasp);
// CFGPass(&clasp).run();
// clasp.1
// run();
// */
//}
//void testUnsafeCode1()
//{
// shared_ptr<Scanner> scanner(new Scanner(L"scripts/cases/bugs-code.xreate"));
// shared_ptr<Parser> parser(new Parser(scanner.get()));
// parser->Parse();
// flush(cout);
// if (parser->errors->count)
// {
// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
// exit(1);
// }
// AST& root = parser->root;
// ClaspLayer clasp;
// /*
// FunctionTagsPass(root).run(clasp);
// RulesPass(root).run(clasp);
// CFGPass(&clasp).run();
// //clasp.addRule(":- call(X, Y), tag(Y, unsafe), not tag(X, unsafe), function(X), function(Y).");
// clasp.run();
// */
//}
//void test_DFG_1()
//{
// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
// shared_ptr<Parser> parser(new Parser(scanner.get()));
// parser->Parse();
// flush(cout);
// if (parser->errors->count)
// {
// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
// exit(1);
// }
// PassManager m;
// m.clasp = new ClaspLayer();
// m.llvm = new LLVMLayer(&parser->root);
// m.root = & parser->root;
// m.clasp->ast = m.root;
// m.registerPass(new DFAPass(&m));
// m.run();
// m.clasp->run();
// m.root->compile(*m.llvm);
// m.root->run(*m.llvm);
//}
//void test_Xml_1()
//{
// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
// shared_ptr<Parser> parser(new Parser(scanner.get()));
// parser->Parse();
// flush(cout);
// if (parser->errors->count)
// {
// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
// exit(1);
// }
// PassManager m;
// m.root = & parser->root;
// m.clasp = new ClaspLayer();
// m.clasp->ast = m.root;
// m.llvm = new LLVMLayer(&parser->root);
// m.registerPass(new DFAPass(&m));
// m.run();
//}
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 1f63042..0967945 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,129 +1,130 @@
/*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(Types, DependantTypes1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeXmlNode = program->root->findType("XmlNode");
ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator);
ASSERT_EQ(2, typeXmlNode->__operands.size());
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value);
}
TEST(Types, DependantTypes2) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Template = type Template(Leaf) [Leaf, [Leaf[content]]]."
"Concrete = type alias Template(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
}
TEST(Types, TreeType1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
auto typeLink = typeConcrete->__operands.at(1).__operands.at(0);
ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId);
}
TEST(Types, TreeType1LLvm){
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
TEST(Types, ArrayOfExternal1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symb = body->findSymbol("childrenRaw");
const TypeAnnotation& t = CodeScope::findDefinition(symb);
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
}
TEST(Types, ExternType1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symbTree = body->findSymbol("tree");
const TypeAnnotation& t = CodeScope::findDefinition(symbTree);
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
}
+//TEST string type
diff --git a/cpp/tests/upcoming.cpp b/cpp/tests/upcoming.cpp
new file mode 100644
index 0000000..fc248d1
--- /dev/null
+++ b/cpp/tests/upcoming.cpp
@@ -0,0 +1,5 @@
+#include "gtest/gtest.h"
+
+TEST(AST, DISABLED_functionModification){
+ //x = find single (...), where single - is a modification sign of a base function 'find'
+}
diff --git a/cpp/tests/xml.cpp b/cpp/tests/xml.cpp
new file mode 100644
index 0000000..cb62100
--- /dev/null
+++ b/cpp/tests/xml.cpp
@@ -0,0 +1,31 @@
+#include "passmanager.h"
+#include "Scanner.h"
+
+#include "gtest/gtest.h"
+
+using namespace xreate;
+
+TEST(Xml, Main){
+ FILE* input = fopen("scripts/xml/input.xreate", "r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ PassManager* program = PassManager::prepareForCode(scanner);
+
+ void* mainPtr = program->run();
+ int (*main)() = (int (*)())(intptr_t)mainPtr;
+
+ int answer = main();
+}
+
+TEST(Xml, DISABLED_AliasTuple){
+
+}
+
+TEST(Xml, DISABLED_FoldProtoEnhanced){
+
+}
+
+TEST(Xml, DISABLED_TransfucPropagation){
+
+}
diff --git a/project/subsystems.graphmlz b/project/subsystems.graphmlz
deleted file mode 100644
index 571f723..0000000
Binary files a/project/subsystems.graphmlz and /dev/null differ
diff --git a/scripts/environment-tests/current b/scripts/environment-tests/current
new file mode 100644
index 0000000..ba337ec
--- /dev/null
+++ b/scripts/environment-tests/current
@@ -0,0 +1,8 @@
+// install cmake
+// install llvm
+// install gcc
+// install gtest
+
+function():: testEnvironment(exists(gcc)){
+ exec("gcc -v") :: expectNoErrors.
+}
diff --git a/scripts/environment-tests/xreate-environment b/scripts/environment-tests/xreate-environment
new file mode 100644
index 0000000..f7428c8
--- /dev/null
+++ b/scripts/environment-tests/xreate-environment
@@ -0,0 +1,60 @@
+// install cmake
+// install llvm
+// install gcc
+// install gtest
+
+function():: TestEnvironment(exists(gcc)){
+ exec("gcc -v") :: ExpectNoErrors; log("Check gcc").
+}
+
+function():: provide(gcc) {
+ exec("sudo apt-get install gcc"):: log("[GCC] Installation").
+}
+
+function():: TestEnvironment(exists(cmake)){
+ exec("cmake /V"):: ExpectNoErrors; log("Check cmake").
+}
+
+function():: provide(cmake) {
+ exec("sudo apt-get install cmake"):: log("[CMake] Installation").
+}
+
+function():: TestEnvironment(exists(subversion)){
+ exec("svn --version"):: ExpectNoErrors; log("Check svn").
+}
+
+function():: provide(subversion) {
+ exec("sudo apt-get install subversion"):: log("[Subversion] Installation").
+}
+
+function():: TestEnvironment(exists(scons)){
+ exec("scons -v"):: ExpectNoErrors; log("Check scons").
+}
+
+function():: provide(scons) {
+ exec("sudo apt-get install scons"):: log("[Scons] Installation").
+}
+
+function():: TestEnvironment(exists(bison)){
+ exec("bison --version"):: ExpectNoErrors; log("Check bison").
+}
+
+function():: provide(bison) {
+ exec("sudo apt-get install bison"):: log("[Bison] Installation").
+}
+
+//FEATURE dependent packages: Subversion
+function():: provide(gringo)
+{
+ exec("cd /opt"). //FEATURE states: dir("/opt")
+ exec("svn://svn.code.sf.net/p/potassco/code/trunk")
+ :: log("[Potassco] cloning latest version");
+ require(svn); require(rights("/opt", WRITE)). //"sudo chown -R user ./potassco"
+
+ //
+ exec("scons --build-dir=release"):: require(scons)
+}
+
+function()::{
+
+}
diff --git a/scripts/function-modifications/control-context.lp b/scripts/function-modifications/control-context.lp
new file mode 100644
index 0000000..22d3247
--- /dev/null
+++ b/scripts/function-modifications/control-context.lp
@@ -0,0 +1 @@
+function_mod(func1, mod1):- %context condition
diff --git a/scripts/function-modifications/current b/scripts/function-modifications/current
new file mode 100644
index 0000000..1cbf57d
--- /dev/null
+++ b/scripts/function-modifications/current
@@ -0,0 +1,92 @@
+interface(extern-c){
+xml2 = library:: pkgconfig(\"libxml-2.0\")
+ [\"libxml/tree.h\"].
+
+include [xml2].
+}
+
+
+a = function()::int;
+ enrty; bug(2530)
+{
+ <entry; bug(2530)>
+
+}
+
+interface(cfg){
+ context operator map:: hfgfgfgf
+ context function a:: optimization: mem
+}
+
+function a :: entry;
+}
+
+a<int>::int.
+
+
+result = fold(vector->el, zero -> acc) {
+
+}
+
+
+main:: entry; bug(2711); unsafe; permissions(usb_access) = function(a::int, b::int)::string; {
+}
+
+a = function()<int>
+context
+main = function (a::xxs, b::fefe -> r::fdfd):: fdfdfd case attr x:: AA, BB
+ {
+ <optimization: mem>
+ context:: {
+ frdkfkfe
+ }
+
+ }
+
+ case attr <optimize: mem>
+ <AAA, BBB> {
+ a() + b().
+ }
+
+ {
+ <AAA, BBB>
+
+ }
+
+ context:: optimization: mem; warnings: off
+ {
+
+ } {
+
+ case <odd> {
+ result = a() + b() :: <odd>
+ }
+
+ case a::odd {
+
+ }
+
+ context<odd; asasa>
+ result = a() + b() :: odd.
+
+ result = a()::odd + b().
+}
+
+
+a = function() {}{}{}{} {}{}{}{}{}{}{}{}{}{}{}{}{}
+
+argument
+function
+result
+function context
+
+annotation several values, annotation sole value;
+function xxs;fdfdfd;fdfd, fdfd;qwqwq;trtrt;iui, aaa;bbb -> qqq; www
+ :: entry
+ <warnings: off>
+ case <optimization: mem> {
+ <warnings: important>
+ a() + b()
+ }
+
+
diff --git a/scripts/function-modifications/data-context.lp b/scripts/function-modifications/data-context.lp
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/scripts/function-modifications/data-context.lp
@@ -0,0 +1 @@
+
diff --git a/scripts/input.xreate b/scripts/input.xreate
deleted file mode 100644
index bb95705..0000000
--- a/scripts/input.xreate
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-/* local scope doc ptr */
-
-
-XmlNode = type alias {
- tag:: string,
- /* attrs:: [string],*/
- content:: string
-}.
-
-interface(extern-c){
- xml2 = library:: pkgconfig("libxml-2.0").
-
- include {
- xml2 = ["libxml/tree.h", "string.h"]
- }.
-}
-
-Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
-XmlTree = type alias Tree(XmlNode).
-
-Alias = type alias [String, String].
-AliasList = type alias [Alias].
-
-
-classesAliasQuery = function(node:: xmlNodePtr):: Alias
-{
- classesPara = ["pgess1", "pgess2"] :: [String].
-
-
- result =
- case default {none}
-
- case node[tag] == "style", class in classesPara,
- classAlias = node[attrs, "name"],
- class=node[attrs, "parent-style-name"],
- {
- [classAlias. class]
- }.
-
- result.
-}
-
-
-dictAliases = function():: AliasList{
- filename = "project/documentation.fodt" :: string.
- docRaw = xmlParseFile(filename) :: xmlDocPtr.
- tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
-
- nodeStylesRoot = find(tree, "automatic-styles"):: xmlNodePtr.
- nodesStyles= nodeStylesRoot["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
-
- dictAliases = loop fold(nodesStyles->nodeStyle:: xmlNodePtr, []->aliases::[xmlNodePtr]):: [xmlNodePtr] {
- aliases + classAliasesQuery(nodeStyle).
- }.
-
- dictAliases
-}
-
-test1 = function():: int; entry {
- dictAliases = dictAliases():: AliasList.
-
- count = loop fold(dictAliases->alias::Alias, 0->count::int):: int{
- aliasName = alias[0]:: String; logging.
- aliasOrigClass = alias[1]::String; logging.
-
- 0 + strlen(aliasName) + strlen(aliasOrigClass).
- }
-
- count
-}
-
-/*
-toXmlNode = function (nodeRaw:: xmlNodePtr):: XmlNode
-{
- {tag = nodeRaw["name"], content=null}
-}
-
-
-children = function (tree:: xmlNodePtr):: XmlTree
-{
- childrenRaw = tree["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
-
- loop map (childrenRaw->childRaw:: xmlNodePtr):: XmlTree {
- [toXmlNode(childRaw), children(childRaw)]
- }
-}
-
-
-document = function (filename:: string):: XmlTree
-{
- docRaw = xmlParseFile(filename) :: xmlDocPtr.
- nodeRaw= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
-
- [toXmlNode(nodeRaw), children(nodeRaw)]:: XmlTree
-}
-
-*/
-
-
-
-
-
-
-
diff --git a/scripts/xml/xml-client.xreate b/scripts/xml/[old] xml-client.xreate
similarity index 63%
rename from scripts/xml/xml-client.xreate
rename to scripts/xml/[old] xml-client.xreate
index dc1b2cb..5ea610f 100644
--- a/scripts/xml/xml-client.xreate
+++ b/scripts/xml/[old] xml-client.xreate
@@ -1,71 +1,112 @@
/*
Example of c++ code:
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname.c_str());
if (doc == NULL ) {
fprintf(stderr,"Document not parsed successfully. \n");
return;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
printf("child: %s\n", cur->name);
cur = cur->next;
}
*/
/*
Default strategies:
- what to do with unspecified nodes
Node content strategy:
- send as-is
- apply transforms (all / named)
- ?? skip
Processing order:
- dependencies
*/
+
+ default_filname = "project/documentation.fodt" : string;
+
+/* require ptrvalid */
+/* local scope doc ptr */
+
+XmlNode = type {
+ tag: string;
+ attrs: [string];
+ content: string}.
+
+Tree = type(Leaf) Tree [Leaf; [Tree(Leaf)]];
+
+XmlTree = Tree(XmlNode);
+
+
+children = function: (tree: xmlNodePtr)->XmlTree
+{
+ childrenRaw = tree[xmlChildrenNode]: [xmlNodePtr], linkedlist(next, null);
+
+ map (childrenRaw->childRaw: xmlNodePtr) {
+ Tree[childRaw[name] children(childRaw)]
+ }
+}
+
+
+document = function: (filename: string)->XmlTree
+{
+ docRaw = xmlParseFile(docname.c_str()) : xmlDocPtr;
+ nodeRaw= xmlDocGetRootElement(docRaw) : xmlNodePtr;
+
+ Tree [nodeRaw[name] children(nodeRaw));
+}
+
query = function(tree: XmlTree): [XmlTree]
{
children : context(children) =
case default
[]
case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
{
loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
{accum + traverse(child): cases(transFilters) };
}
node =
case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
{
[class, node[attrs, "style:display-name"]];
}
case default
[] ;
Tree[node children] | node + children
}
+test = function: ()->num
+{
+ data = query(document(default_filename)): [string, string];
+
+ exists(data, "pgess1").
+}
+
/*
traverse = function(trees: [XmlTree]) : [XmlTree]
loop fold(trees->tree: Tree; []->acc)
acc + traverse(tree)
*/
\ No newline at end of file
diff --git a/scripts/xml/all.xreate b/scripts/xml/all.xreate
new file mode 100644
index 0000000..3cd606f
--- /dev/null
+++ b/scripts/xml/all.xreate
@@ -0,0 +1,188 @@
+/* C++ SECTION
+Example of c++ code:
+
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ doc = xmlParseFile(docname.c_str());
+ if (doc == NULL ) {
+ fprintf(stderr,"Document not parsed successfully. \n");
+ return;
+ }
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ fprintf(stderr,"empty document\n");
+ xmlFreeDoc(doc);
+ return;
+ }
+
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ printf("child: %s\n", cur->name);
+
+ cur = cur->next;
+ }
+
+*/
+
+/* FEATURES SECTION
+
+ Default strategies:
+ - what to do with unspecified nodes
+
+ Node content strategy:
+ - send as-is
+ - apply transforms (all / named)
+ - ?? skip
+
+ Processing order:
+ - dependencies
+
+ Mapping:
+ * tree -> list
+
+*/
+
+/* TODO SECTION
+ -- gather types aliases (tree->list mapping)
+ -- flyweight implementation (doc calculation, for example. based on are there more than one opened document )
+*/
+
+// REQUIREMENTS SECTION
+/* require ptrvalid */
+/* local scope doc ptr */
+/* singleton element check(::single) */
+
+XmlAttr = type alias {
+ name:: String,
+ content:: String
+}.
+
+XmlNode = type alias {
+ name:: String, /* the name of the node, or the entity */
+ children:: [xmlNode], /* parent->childs link */
+ content:: String, /* the content */
+ attributes::[XmlAttr] /* properties list */
+
+ /*
+ void *_private; // application data
+ struct _xmlNode *parent; // child->parent link
+ struct _xmlNode *next; // next sibling link
+ struct _xmlNode *prev; // previous sibling link
+ struct _xmlDoc *doc; // the containing document
+ unsigned short line; // line number
+ */
+}.
+
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h", "string.h"]
+ }.
+}
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+find = ..
+[xmlNodePtr]; containers:linkedlist(next, null).
+
+
+
+test1 = function():: int; entry {
+ dictAliases = dictAliases():: AliasList.
+
+ count = loop fold(dictAliases->alias::Alias, 0->count::int):: int{
+ aliasName = alias[0]:: String; logging.
+ aliasOrigClass = alias[1]::String; logging.
+
+ count + 1
+ }
+
+ count
+}
+
+/*
+toXmlNode = function (nodeRaw:: xmlNodePtr):: XmlNode
+{
+ {tag = nodeRaw["name"], content=null}
+}
+
+
+children = function (tree:: xmlNodePtr):: XmlTree
+{
+ childrenRaw = tree["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+
+ loop map (childrenRaw->childRaw:: xmlNodePtr):: XmlTree {
+ [toXmlNode(childRaw), children(childRaw)]
+ }
+}
+
+
+document = function (filename:: string):: XmlTree
+{
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ nodeRaw= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+
+ [toXmlNode(nodeRaw), children(nodeRaw)]:: XmlTree
+}
+
+*/
+
+Alias = type alias {
+ alias: String,
+ original: String
+}.
+
+AliasList = type alias [Alias].
+
+classesPar = ["pgess1", "pgess2"] :: [String].
+classesAliasQuery = function(node:: xmlNodePtr):: Alias
+{
+ result =
+ case default {none}
+
+ case node[tag] == "style", class in classesPara,
+ classAlias = node[attrs, "name"],
+ class=node[attrs, "parent-style-name"],
+ {
+ [classAlias. class]
+ }.
+
+ result.
+}
+
+
+
+dictAliases = function():: AliasList{
+ filename = "project/documentation.fodt" :: string.
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+
+ nodeStylesRoot = findNodes(tree, "office:automatic-styles"):: xmlNodePtr; single.
+ nodesStyles= findNodes(nodeStylesRoot, "style:style"):: [xmlNodePtr].
+
+ nodesChildAliases = filter(nodeStyles){
+ "style:parent-style-name" in classesPar
+ }
+
+ dictChildAliases = loop fold(nodesChilds->node:: xmlNodePtr, []->aliases::[Alias]) {
+ aliases + {alias = attr(node, "style:name"), original = attr(node, "style:parent-style-name")}
+ }.
+
+ nodesDisplayAliases = filter(nodesStyles){
+ "style:parent-style-name" in classesPar
+ }
+
+ dictDisplayAliases = loop fold(nodesDisplayAliases->node:: xmlNodePtr, []->aliases::[Alias]) {
+ aliases + {alias = attr(node, "style:display-name"), original = attr(node, "style:name")}
+ }.
+
+ nodesDisplayAliases + dictDisplayAliases
+}
+
+
+
+
+
+
diff --git a/scripts/xml/input.xreate b/scripts/xml/input.xreate
new file mode 100644
index 0000000..e763d7f
--- /dev/null
+++ b/scripts/xml/input.xreate
@@ -0,0 +1,142 @@
+/* C++ SECTION
+Example of c++ code:
+
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ doc = xmlParseFile(docname.c_str());
+ if (doc == NULL ) {
+ fprintf(stderr,"Document not parsed successfully. \n");
+ return;
+ }
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ fprintf(stderr,"empty document\n");
+ xmlFreeDoc(doc);
+ return;
+ }
+
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ printf("child: %s\n", cur->name);
+
+ cur = cur->next;
+ }
+
+*/
+
+/* FEATURES SECTION
+
+ Default strategies:
+ - what to do with unspecified nodes
+
+ Node content strategy:
+ - send as-is
+ - apply transforms (all / named)
+ - ?? skip
+
+ Processing order:
+ - dependencies
+
+ Mapping:
+ * tree -> list
+
+*/
+
+/* TODO SECTION
+ -- gather types aliases (tree->list mapping)
+ -- flyweight implementation ('doc' field calculation, for example. based on are there more than one opened document )
+*/
+
+// REQUIREMENTS SECTION
+/* require ptrvalid */
+/* local scope doc ptr */
+/* singleton element check(::single) */
+
+XmlAttr = type alias {
+ name:: string,
+ content:: string
+}.
+
+XmlNode = type alias {
+ name:: string, /* the name of the node, or the entity */
+
+ content:: string, /* the content */
+ attributes::[XmlAttr] /* properties list */
+
+ /*
+ children:: [xmlNode], // parent->childs link
+
+ void *_private; // application data
+ struct _xmlNode *parent; // child->parent link
+ struct _xmlNode *next; // next sibling link
+ struct _xmlNode *prev; // previous sibling link
+ struct _xmlDoc *doc; // the containing document
+ unsigned short line; // line number
+ */
+}.
+
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h", "string.h"]
+ }.
+}
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+toXmlNode = function (nodeRaw:: xmlNodePtr):: XmlNode
+{
+ propertiesRaw = nodeRaw["properties"]:: [xmlAttrPtr]; containers:linkedlist(next, null).
+ properties = loop map(propertiesRaw -> property::xmlAttrPtr)::[XmlAttr]{
+ {name=property["name"], content=property["children", "content"]}
+ }.
+
+ {name = nodeRaw["name"],
+ content=nodeRaw["content"],
+ attributes=properties}
+}
+
+children = function(nodeRaw::xmlDocPtr)::[XmlTree] {
+ childrenRaw = nodeRaw["children"]:: [xmlDocPtr]; containers:linkedlist(next, null).
+
+ children = loop map(childrenRaw->child:: xmlDocPtr) :: [XmlTree]{
+ [toXmlNode(child), children(child)]
+ }.
+
+ children
+}
+
+document = function (filename:: string):: XmlTree
+{
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ nodeRaw= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+
+ [toXmlNode(nodeRaw), children(nodeRaw)]:: XmlTree
+}
+
+traverse = function(tree:: XmlTree) :: [XmlNode] {
+ listOfNodes = loop fold(tree -> node:: XmlTree, []->acc:: [XmlNode]):: [XmlNode]{
+ acc + node[0] + traverse(node[1]):: [XmlNode]
+ }.
+
+ listOfNodes
+}
+
+test1 = function():: int; entry {
+ filename = "project/documentation.fodt" :: string.
+
+ root = document(filename):: XmlTree.
+ nodesAll = traverse(root):: [XmlNode].
+
+ result = loop fold(nodesAll->node:: XmlNode, 0->count::int):: int{
+ count + if (0==strcmp(node["name"], "section")) :: int {
+ 1
+ } else {
+ 0
+ }
+ }.
+
+ result
+}
diff --git a/scripts/xml/xml-backup.xreate b/scripts/xml/xml-backup.xreate
deleted file mode 100644
index 7fe9246..0000000
--- a/scripts/xml/xml-backup.xreate
+++ /dev/null
@@ -1,65 +0,0 @@
-default_filname = "project/documentation.fodt" : string;
-
-/* require ptrvalid */
-/* local scope doc ptr */
-
-XmlNode = type {
- tag: string;
- attrs: [string];
- content: string}.
-
-Tree = type(Leaf) Tree [Leaf; [Tree(Leaf)]];
-
-XmlTree = Tree(XmlNode);
-
-
-children = function: (tree: xmlNodePtr)->XmlTree
-{
- childrenRaw = tree[xmlChildrenNode]: [xmlNodePtr], linkedlist(next, null);
-
- map (childrenRaw->childRaw: xmlNodePtr) {
- Tree[childRaw[name] children(childRaw)]
- }
-}
-
-
-document = function: (filename: string)->XmlTree
-{
- docRaw = xmlParseFile(docname.c_str()) : xmlDocPtr;
- nodeRaw= xmlDocGetRootElement(docRaw) : xmlNodePtr;
-
- Tree [nodeRaw[name] children(nodeRaw));
-}
-
-
-query = function: (tree: XmlTree) [string, string]
-{
- children : context(children) =
- case default
- []
-
- case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
- {
- loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
- {accum + traverse(child): cases(transFilters) };
- }
-
- node =
- case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
- {
- [class, node[attrs, "style:display-name"]];
- }
-
- case default
- [] ;
-
- node + children;
-}
-
-
-test = function: ()->num
-{
- data = query(document(default_filename)): [string, string];
-
- exists(data, "pgess1").
-}
diff --git a/scripts/xml/xml-query.xreate b/scripts/xml/xml-query.xreate
deleted file mode 100644
index 60a330e..0000000
--- a/scripts/xml/xml-query.xreate
+++ /dev/null
@@ -1,38 +0,0 @@
-XmlNode = type {
- tag: string;
- attrs: [string];
- content: string}.
-
-Tree = type(Leaf) Tree [Leaf; [Tree(Leaf)]].
-
-XmlTree = Tree(XmlNode).
-
-query = function(tree: XmlTree): [XmlTree]
-{
- children : context(children) =
- case default
- []
-
- case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
- {
- loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
- {accum + traverse(child): cases(transFilters) };
- }
-
- node =
- case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
- {
- [class, node[attrs, "style:display-name"]];
- }
-
- case default
- [] ;
-
- Tree[node children] | node + children
-}
-
- /*
-traverse = function(trees: [XmlTree]) : [XmlTree]
- loop fold(trees->tree: Tree; []->acc)
- acc + traverse(tree)
- */
\ No newline at end of file
diff --git a/tools/testrender/CMakeLists.txt b/tools/testrender/CMakeLists.txt
index 690ae5f..b87e502 100644
--- a/tools/testrender/CMakeLists.txt
+++ b/tools/testrender/CMakeLists.txt
@@ -1,5 +1,10 @@
project(testrender)
cmake_minimum_required(VERSION 2.8)
+INCLUDE_DIRECTORIES("/usr/include/libxml2")
+set(CMAKE_BUILD_TYPE Debug)
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -std=c++11")
+
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
+target_link_libraries(${PROJECT_NAME} -lxml2)
diff --git a/tools/testrender/main.cpp b/tools/testrender/main.cpp
index 5f5419b..d86ce29 100644
--- a/tools/testrender/main.cpp
+++ b/tools/testrender/main.cpp
@@ -1,10 +1,134 @@
#include <iostream>
+#include <stdlib.h>
+#include <boost/format.hpp>
+#include <string>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <map>
+#include <list>
+#include <set>
using namespace std;
+char* pathTestsOutput = "/tmp/xreate-tests-output-XXXXXX";
+const string& pathComponentsGraph = "/private/prg/code/xreate/project/subsystems.graphml";
+
+map<string, bool> tests;
+set<string> testsUnused;
+
+void runTests(){
+ //mkstemp(pathTestsOutput);
+ const string &cmm_export = string("export GTEST_OUTPUT=\"xml:")+ pathTestsOutput +"\"";
+ const string &cmm_chdir = "cd /private/prg/code/xreate/";
+ const string &cmm_runtest = "exec build/xreate";
+
+ const string& comm = boost::str(boost::format("(%1% && %2% && %3%)") % cmm_export % cmm_chdir % cmm_runtest);
+ system(comm.c_str());
+}
+
+void parseTestsOutput(){
+ const string& queryTestCases = "//testcase[@status='run']";
+
+ xmlDocPtr doc = xmlParseFile(pathTestsOutput);
+ xmlXPathContextPtr context = xmlXPathNewContext(doc);
+ xmlXPathObjectPtr testcases = xmlXPathEvalExpression((xmlChar*) queryTestCases.c_str(), context);
+
+ for (int caseId = 0; caseId < testcases->nodesetval->nodeNr; ++caseId) {
+ xmlNodePtr testcase = testcases->nodesetval->nodeTab[caseId];
+
+ string nameTestSuite((const char *) xmlGetProp(testcase->parent, (const xmlChar*)"name"));
+ string nameTestCase((const char *) xmlGetProp(testcase, (const xmlChar*)"name"));
+ bool flagSuccess = (testcase->children)? false: true;
+
+ string testName = nameTestSuite+":"+nameTestCase;
+ tests.emplace(testName, flagSuccess);
+ testsUnused.insert(testName);
+ }
+}
+
+string getTestsResultForComponent(const string& signature){
+ list<string> componentParts;
+ boost::split(componentParts, signature, [](const char& a){return a==',';});
+
+ int resNeg = 0; int resPos = 0; bool flagTestsFound = false;
+ for(auto test: tests){
+ for(const string& signature: componentParts){
+ if (boost::icontains(test.first, signature)){
+ if (test.second){
+ resPos ++;
+ } else {
+ resNeg--;
+ }
+
+ flagTestsFound = true;
+ testsUnused.erase(test.first);
+ break;
+ }
+ }
+ }
+
+ if (!flagTestsFound){
+ cout << "Warning: No tests for "<<signature << endl;
+ }
+
+ return (resNeg!=0)? to_string(resNeg) : to_string(resPos);
+}
+
+void parseComponentsGraph(){
+ const string& queryNode = "//a:node[a:data[@key=\"d4\"]]";
+ const string& queryTestResults = "a:data[@key='d5']";
+ const string& queryTestSignature = "a:data[@key='d4']";
+
+ xmlDocPtr doc = xmlParseFile(pathComponentsGraph.c_str());
+ xmlNodePtr root = xmlDocGetRootElement(doc);
+
+ xmlXPathContextPtr context = xmlXPathNewContext(doc);
+ xmlXPathRegisterNs(context, (xmlChar*) "a", (xmlChar*) "http://graphml.graphdrawing.org/xmlns");
+ xmlXPathObjectPtr setComponents = xmlXPathEvalExpression((xmlChar*) queryNode.c_str(), context);
+
+ for (int nodeId=0; nodeId < setComponents->nodesetval->nodeNr; ++nodeId){
+ xmlNodePtr nodeComponent = setComponents->nodesetval->nodeTab[nodeId];
+ //xmlXPathSetContextNode(node, context);
+ context->node = nodeComponent;
+ xmlXPathObjectPtr setNodeTestSignature = xmlXPathEvalExpression((xmlChar*) queryTestSignature.c_str(), context);
+ assert(setNodeTestSignature->nodesetval->nodeNr==1);
+ char* componentTestsSignature = (char*) xmlNodeGetContent(setNodeTestSignature->nodesetval->nodeTab[0]);
+
+ string componentTestsResult = getTestsResultForComponent(componentTestsSignature);
+
+ xmlXPathObjectPtr setNodeTestResult = xmlXPathEvalExpression((xmlChar*) queryTestResults.c_str(), context);
+
+ if (0 == setNodeTestResult->nodesetval->nodeNr){
+ xmlNodePtr dataTestsResult = xmlNewChild(nodeComponent, NULL, BAD_CAST "data",
+ BAD_CAST componentTestsResult.c_str());
+
+ xmlNewProp(dataTestsResult, BAD_CAST "key", BAD_CAST "d5");
+ continue;
+ }
+ assert(setNodeTestResult->nodesetval->nodeNr == 1);
+ xmlNodePtr dataTestsResult = setNodeTestResult->nodesetval->nodeTab[0];
+ xmlNodeSetContent(dataTestsResult, BAD_CAST componentTestsResult.c_str());
+ }
+
+ xmlSaveFile(pathComponentsGraph.c_str(), doc);
+}
+
+void checkUnusedTests(){
+ for (string test: testsUnused){
+ cout << "Warning: no components use test "<<test << endl;
+ }
+}
+
int main()
{
- cout << "Hello World!" << endl;
+ runTests();
+ parseTestsOutput();
+ parseComponentsGraph();
+ checkUnusedTests();
return 0;
}
Event Timeline
Log In to Comment