No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:38 AM
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