No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:31 AM
diff --git a/coco/gen-xreate b/coco/gen-xreate
deleted file mode 100755
index 132dff9..0000000
--- a/coco/gen-xreate
+++ /dev/null
@@ -1 +0,0 @@
-cococpp -frames /usr/share/coco-cpp/ ./xreate.ATG
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index 44ec3ed..fbe17ca 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,422 +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; .)
+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; .)
+BDecl<CodeScope* scope> = (. Expression body; TypeAnnotation typ; pushContextScope(scope); .)
'{' { (
IF(checkAssignment()) VDecl<scope> '.'
- | ExprTyped<body, typ> (. scope->setBody(body); .)
+ | ExprTyped<body, typ> (. scope->setBody(body); popContextScope(); .)
)}
'}'.
-IfDecl<Expression& e, TypeAnnotation typ, CodeScope* outer> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(outer)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(outer));
- TypeAnnotation typIf; .)
+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, CodeScope* f> =
+LoopDecl<Expression& e, TypeAnnotation& typOut> =
(. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc; TypeAnnotation typEl, typAcc;
- ManagedScpPtr block = root.add(new xreate::CodeScope(f)); .)
+ 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<> = (. TypeAnnotation typ; Expression tag; .)
- ["switch" [tagcolon Type<typ> {';' MetaSimpExpr<tag>}]]
- CaseDecl {CaseDecl}
+SwitchDecl<Expression& eSwitch> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); .)
+ // ["switch" [tagcolon Type<typ> {';' MetaSimpExpr<tag>}]]
+ CaseDecl<eSwitch> {CaseDecl<eSwitch>}
.
-CaseDecl<> = (. Expression e; .)
+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"
- | CalleeParamsNamed
+ | CaseParams<&*scopeCond>
)
- BDecl<nullptr>
+ 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; .)
+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, nullptr>
- | IfDecl<e, typ, nullptr>
- | SwitchDecl
+ | 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)); .)
}.
-CalleeParamsNamed<> =
- CalleeParamNamed
- {',' CalleeParamNamed
- }.
-
-CalleeParamNamed<> = (. Expression arg; TypeAnnotation argtyp; .)
- (
- IF(checkAssignment()) VDecl<new CodeScope()>
- | ExprTyped<arg, argtyp>
- ).
-
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 1cb116b..a0de9f7 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,42 +1,50 @@
{
"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"
- }
+ "function": "bind_func",
+ "scope": "bind_scope"
+ },
+
+ "nonevalue": "nonevalue",
+ "ret": {
+ "symbol": "retv",
+ "tag": "ret"
+ }
},
"tests": {
"template": "default",
"templates": {
"default": "*-",
"types": "Types*-",
"containers": "Containers*-",
"ast": "AST*",
"non-containers": "*-Containers*",
"libxml2": "libxml2*",
- "log": "Logging*"
+ "log": "Logging*",
+ "cfg": "CFG.testLoopContextExists"
}
}
}
diff --git a/core/null.lp b/core/null.lp
new file mode 100644
index 0000000..8006219
--- /dev/null
+++ b/core/null.lp
@@ -0,0 +1,2 @@
+functionRetNull(f):- bind_func(f, retsymbol(X)), bind(X, null), v(X).
+functionRetNull(f):- bind_func(f, retsymbol(X)), dfa_connection(X, Y, alias), bind(Y, null), v(X), v(Y).
\ No newline at end of file
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 30040d4..d3e4c7b 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,141 +1,150 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
find_package(LLVM REQUIRED CONFIG)
-find_package(Qt5Core)
+
+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
- ./tests/tests.cpp ./tests/testClangAPI.cpp ./tests/testJson.cpp ./tests/testBasic.cpp
-
./src/utils.cpp
./src/passmanager.cpp
- ./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp ./src/pass/compilepass.cpp ./src/pass/functiontagspass.cpp
- #./src/pass/cfgpass.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/attachments.cpp
+ ./src/instructions/instr-containers.cpp
+ ./src/query/containers.cpp
+ ./src/query/ptrvalid.cpp
+ ./src/attachments.cpp
- /opt/potassco/gringo-4.4.0-source/app/shared/src/clingocontrol.cc
- /opt/potassco/gringo-4.4.0-source/app/pyclingo/src/clingo_lib.cc
+ #${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
)
-set(POTASSCO_PATH "/opt/potassco/gringo-4.4.0-source")
-INCLUDE_DIRECTORIES("/usr/lib/llvm-3.7/include")
-INCLUDE_DIRECTORIES("/usr/include/libxml2")
+
+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}/app/shared/include
-${POTASSCO_PATH}/app/pyclingo/src
+${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.h tests/testLibXml2.cpp src/ExternLayer.cpp src/ExternLayer.h)
+add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} tests/testLibXml2.cpp src/ExternLayer.cpp src/ExternLayer.h)
-set(COCO_TARGET cocoTarget)
+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-xreate
+ 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_PATH ${POTASSCO_PATH}/build/debug)
-
-#find_library(LIBCLASP_LIBRARY_GRINGO NAMES gringo
-# HINTS ${LIBCLASP_PATH})
-#find_library(LIBCLASP_LIBRARY_CLASP NAMES clasp
-# HINTS ${LIBCLASP_PATH})
-
set(LIBCLASP_LIBS
- ${LIBCLASP_PATH}/libclasp.a
- ${LIBCLASP_PATH}/libgringo.a
- ${LIBCLASP_PATH}/libprogram_opts.a
+ clingo
+ clasp
+ gringo
+ program_opts
+ reify
)
-#set(LIBCLANG_PATH "/usr/lib/llvm-3.7/lib/")
-#set(LIBCLANG_LIBS
-##/usr/lib/llvm-3.7/lib/libclangToolingCore.a
-#/usr/lib/llvm-3.7/lib/libclangTooling.a
-#)
-
-file(GLOB_RECURSE LIBCLANG_LIBS2 /usr/lib/llvm-3.7/lib/*.a)
-
-set(LIBCLANG_LIBS
-/usr/lib/llvm-3.7/lib/libclangParse.a
-/usr/lib/llvm-3.7/lib/libclangFormat.a
-${LIBCLANG_LIBS2}
-${LIBCLANG_LIBS2}
-/usr/lib/llvm-3.7/lib/libclangParse.a
-/usr/lib/llvm-3.7/lib/libclangFormat.a
-)
-
-message(STATUS "ALL LIBS: " ${LIBCLANG_LIBS})
-
-
-message(STATUS ${LIBCLASP_LIBS})
+message(STATUS "CLANG LIBS: " ${CLANG_LIBS})
+message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS})
add_definitions(-DWITH_THREADS=0)
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})
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
-target_link_libraries(xreate ${GTEST_LIBRARIES} ${llvm_libs} ${LIBCLANG_LIBS} pthread xml2 Qt5::Core ${LIBCLASP_LIBS} gcov)
+# -fprofile-arcs -ftest-coverage -O0
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall")
+
+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 1b95b7e..6d8c5c1 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,274 +1,276 @@
//
// Created by pgess on 4/21/15.
//
#include "ExternLayer.h"
-#include "QStringList"
#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;
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)
{}
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 (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;
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";
}
}
}
void
ExternLayer::init(const AST* root) {
addExternalData(root->__externdata);
- QStringList code;
+ list<string> code;
std::vector<string> args{
- "-I/usr/local/include"
- ,"-I/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0/include"
- ,"-I/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include"
- ,"-I/usr/include/x86_64-linux-gnu"
- ,"-I/usr/include"
+ "-I/usr/include"
+ ,"-I/usr/local/include"
+ ,"-I/usr/lib/llvm-3.6/lib/clang/3.6.0/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()),
- [](const string header ) {
- QString line = QString("#include \"%1\"").arg(header.c_str());
- llvm::outs()<< "<" << line.toStdString() << "> ";
+ [&formatInclude](const string header ) {
+ string line = boost::str(formatInclude % header);
+ llvm::outs()<< "<" << line << "> ";
return line;
});
llvm::outs() << '\n';
}
-
- loadLibraries(move(libs));
- ast = buildASTFromCodeWithArgs(code.join('\n').toStdString(), args);
+ //TODO uncomment loadLibraries
+ //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/ExternLayer.h b/cpp/src/ExternLayer.h
index cc2a18f..ab41749 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,55 +1,55 @@
//
// Created by pgess on 4/21/15.
//
#ifndef XREATE_EXTERNLAYER_H
#define XREATE_EXTERNLAYER_H
#include "llvmlayer.h"
#include <vector>
#include <string>
#include <map>
#include "ast.h"
#include "clang/AST/ASTContext.h"
-#include "/private/prg/vendors/clang/lib/CodeGen/CodeGenModule.h"
+#include "/opt/llvm-toolchain-3.6-3.6/clang/lib/CodeGen/CodeGenModule.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
namespace xreate {
struct ExternData {
void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
void addIncludeDecl(Expression&& e);
std::vector<ExternEntry> entries;
std::map<std::string, std::string> __dictLibraries;
};
class ExternLayer {
public:
ExternLayer(LLVMLayer* llvm);
llvm::Function* lookupFunction(const std::string& name);
clang::QualType lookupType(const std::string& id);
std::vector<std::string> getStructFields(const clang::QualType& ty);
llvm::Type* toLLVMType(const clang::QualType& t);
bool isPointer(const clang::QualType& t);
void init(const AST* root);
static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
private:
std::unique_ptr<clang::ASTUnit> ast;
std::unique_ptr<clang::CodeGen::CodeGenModule> __cgm;
std::unique_ptr<clang::CodeGenOptions> __cgo;
llvm::DataLayout __datalayout;
LLVMLayer* __llvm;
std::vector<ExternEntry> entries;
std::map<std::string, llvm::Function*> __functions;
void addExternalData(const std::vector<ExternEntry>& data);
void loadLibraries(std::vector<std::string>&& libs);
};
}
#endif //XREATE_EXTERNLAYER_H
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 6f7b723..6db5f2f 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,637 +1,642 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
-#include <QString>
#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)
{
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)
{}
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));
__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);
}
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())
{}
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 769b295..973ea60 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,511 +1,518 @@
#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 {};
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
+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;
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;
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 34a7708..751e072 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,482 +1,611 @@
#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 <clingocontrol.hh>
-
#include <iostream>
-#include <clingo_lib.hh>
+#include <clingo/clingocontrol.hh>
#include "utils.h"
+#include <boost/format.hpp>
+#include <boost/algorithm/string/join.hpp>
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;
}
- QStringList multiplyLists(std::list<QStringList> &&lists) {
- QStringList result = lists.front();
+ list<string>
+ multiplyLists(list<list<string>> &&lists) {
+ typedef list<string> StringList;
+ assert(lists.size());
+ StringList result(*lists.begin());
lists.pop_front();
- for (QStringList &list: lists) {
- QStringList::const_iterator end = result.end();
- for (QStringList::iterator expr1I = result.begin(); expr1I < end; ++expr1I) {
+ 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;
- QStringList::const_iterator expr2I = list.begin();
+ StringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
- result.append(QString("%1, %2").arg(*expr1I).arg(*expr2I));
+ result.push_back(str(concat %(*expr1I) %(*expr2I)));
- *expr1I = QString("%1, %2").arg(*expr1I).arg(*expr2I);
+ *expr1I = str(concat %(*expr1I) %(*expr2I));
}
}
return result;
}
void
- ClaspLayer::addCFAData(CFGraph &&graph) {
- ostream &cout = __partGeneral;
-
- cout << endl << "%\t\tStatic analysis: CFA" << endl;
-
- for (const std::pair<unsigned int, unsigned int> &relation: graph.__relations) {
- const string &tagFrom = graph.__nodes.at(relation.first);
- const string &tagTo = graph.__nodes.at(relation.second);
-
- cout << (QString("call(%1, %2) .").arg(tagFrom.c_str()).arg(tagTo.c_str())).toStdString() << endl;
- }
+ 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 format2Args("(%1%, %2%)");
for (i1= dfaData.__edges.begin(), i2 = dfaData.__data.begin(); i1!= dfaData.__edges.end(); ++i1, ++i2 )
{
- QString edgeData;
+ string edgeName;
switch (*i2)
{
- case DFGConnection::OPT: edgeData = "opt"; break;
- case DFGConnection::ALIAS: edgeData = "alias"; break;
- case DFGConnection::PROTO: edgeData = "proto"; break;
+ case DFGConnection::OPT: edgeName = "opt"; break;
+ case DFGConnection::ALIAS: edgeName = "alias"; break;
+ case DFGConnection::PROTO: edgeName = "proto"; break;
}
- cout << QString("dfa_connection(%1, %2, %3).")
- .arg(QString("(%1, %2)").arg(i1->first.identifier).arg(i1->first.scope))
- .arg(QString("(%1, %2)").arg(i1->second.identifier).arg(i1->second.scope))
- .arg(edgeData).toStdString() << endl;
+ cout << "dfa_connection"<< (format3Args
+ %(format2Args %(i1->first.identifier) %(i1->first.scope))
+ %(format2Args %(i1->second.identifier) %(i1->second.scope))
+ %edgeName)
+ << "." <<endl;
symbols.insert(i1->first);
symbols.insert(i1->second);
}
+ boost::format formatBind("bind(%1%, %2%).");
for (const pair<SymbolPacked, Expression>& tag: dfaData.__tags)
{
- for (QString variant: compile(tag.second)) {
- cout << QString("bind(%1, %2).")
- .arg(QString("(%1, %2)").arg(tag.first.identifier).arg(tag.first.scope))
- .arg(variant).toStdString()<<endl;
+ for (string variant: compile(tag.second)) {
+ cout << (formatBind
+ % (format2Args %(tag.first.identifier) %(tag.first.scope))
+ % (variant))
+ << endl;
}
symbols.insert(tag.first);
}
for (const SymbolPacked& s: symbols)
{
- cout << QString("v((%1, %2)).").arg(s.identifier). arg(s.scope).toStdString()<<endl;
+ cout << "v(" << format2Args % (s.identifier) % arg(s.scope) << ")."<<endl;
}
}
void
- ClaspLayer::addFunctionTags(const std::string &function, const std::vector<Tag> &tags) {
+ 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;
+
- cout << (QString("function(%1) .").arg(function.c_str())).toStdString() << std::endl;
+ for (const auto& tag_: boost::make_iterator_range(cfagraph.__functionTags.equal_range(function.first))){
+ const Tag& tag = tag_.second;
- int tagsCount = 0;
- for (const Tag &tag: tags) {
- QStringList tagRaw = compile(tag.first);
- assert(tagRaw.size() == 1);
+ list<string> tagRaw = compile(tag.first);
+ assert(tagRaw.size() == 1);
- std::string atom_binding = Config::get("clasp.bindings.function");
- cout << QString("%1(%2, %3).").arg(atom_binding.c_str()).arg(function.c_str()).arg(tagRaw.at(0)).toStdString() << endl;
- ++tagsCount;
+ cout << formatBind
+ % (atomBinding)
+ % (function.second)
+ % (tagRaw.front())
+ << endl;
+ ++counterTags;
+ }
}
- if (tagsCount == 0) {
+ 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%).");
+ 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;
- QStringList domains;
+ list<string> domains;
+ boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
- [](const std::pair<std::string, DomainAnnotation> &argument) {
+ [&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 QString("%1(%2)").arg(domain.c_str()).arg(argument.first.c_str());
+ return boost::str(formatDef % domain % argument.first);
});
- QStringList vars;
+ 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();
});
- std::list<QStringList> guardsRaw;
+ list<list<string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return compile(guard);
});
- QStringList guards = multiplyLists(std::move(guardsRaw));
- QStringList &&branches = compileNeg(rule.__condition);
+ const list<string>& guards = multiplyLists(std::move(guardsRaw));
+ list<string> &&branches = compileNeg(rule.__condition);
- for (const QString &guardsJoined: guards)
- for (const QString &branch: branches) {
+ 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));
- QString result = QString("warning(%1, (%2)):- %3, %4, %5.")
- .arg(hook)
- .arg(vars.join(", "))
- .arg(branch)
- .arg(guardsJoined)
- .arg(domains.join(", "));
-
- __partGeneral << result.toStdString() << endl;
+ __partGeneral << formatWarning
+ %(hook)
+ %(boost::algorithm::join(vars, ", "))
+ %(branch)
+ %(guardsJoined)
+ %(boost::algorithm::join(domains, ", "))
+ <<endl;
}
}
- QStringList
+ std::list<std::string>
ClaspLayer::compile(const Expression &e) const {
- QStringList result;
+ list<string> result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
- std::list<QStringList> operands;
+ 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);
});
- QStringList &&operands_ = multiplyLists(std::move(operands));
- result.append(QString("%1(%2)").arg(e.__valueS.c_str()).arg(operands_.join(", ")));
+ 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);
- QStringList &&rawOp = compile(op);
+ list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
- result.append(QString("not %1").arg(rawOp.at(0)));
+ result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::NONE: {
switch (e.__state) {
case Expression::IDENT:
- result.append(QString(e.__valueS.c_str()));
+ result.push_back(e.__valueS);
break;
case Expression::NUMBER:
- result.append(QString::number(e.__valueD));
+ result.push_back(to_string(e.__valueD));
break;
default:
assert(true);
}
break;
}
}
+ if (e.isNone()){
+ result.push_back(e.__valueS);
+ }
+
+ assert(result.size());
return result;
}
- QStringList
+ std::list<std::string>
ClaspLayer::compileNeg(const Expression &e) const {
- QStringList result;
+ list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
- QStringList operands1 = compile(e.operands.at(0));
- QStringList operands2 = compile(e.operands.at(1));
+ 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.append(QString("%1, not %2").arg(op1).arg(op2));
+ result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
- QStringList &&rawOp = compile(op);
+ list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
- result.append(rawOp.at(0));
+ 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::addImports() {
+ 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() {
- addImports();
+ involveImports();
+ involveCFAData();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
const char *argv[] = {nullptr, nullptr};
- ClingoLib ctl(2, argv);
+ DefaultGringoModule moduleDefault;
+ ClingoLib ctl(moduleDefault, 2, argv);
//prg.add("p", ["t"], "q(t).")
Gringo::FWStringVec vars{};
ctl.add("base", vars, program.str());
//prg.ground([("p", [2])])
Gringo::Control::GroundVec vals{std::make_pair("base", Gringo::FWValVec {})};
ctl.ground(vals, Gringo::Any());
//solve
Gringo::Control::Assumptions as;
Gringo::SolveResult result = ctl.solve(Gringo::Control::ModelHandler([&](Gringo::Model const &model) {
return this->onModel(model);
}), std::move(as));
if (result == Gringo::SolveResult::SAT) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process clasp data
for (IQuery* q: __queries)
{
q->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
ClaspLayer::ModelRange
ClaspLayer::query(const std::string& atom)
{
if (! __model.count(atom)){
return boost::none;
}
return ModelRange(__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)
{
- auto pos = __indexScopes.emplace(symbol.scope, __indexScopes.size());
- if (pos.second)
- __registryScopes.push_back(symbol.scope);
-
SymbolPacked result;
- result.scope = pos.first->second;
+
+ result.scope = pack(symbol.scope);
result.identifier = symbol.identifier;
return result;
}
Symbol
ClaspLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
};
/*
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;
}
*/
/*****************************************
- * CFGraph
+ * CFAGraph
*****************************************
*/
-
void
- CFGraph::addNode(unsigned int function, std::string &&tag) {
- __nodes.emplace(function, tag);
+ CFAGraph::addFunctionNodeTags(const std::string& function, const std::vector<Tag>&tags) {
+ unsigned int fid = registerNodeFunction(function);
+
+ for (Tag tag: tags){
+ __functionTags.emplace(fid, tag);
+ }
}
- bool
- CFGraph::existsNode(unsigned int function) const {
- return __nodes.count(function);
+ void
+ CFAGraph::addScopeNodeTags(const ScopePacked& scope, const std::vector<Expression>& tags){
+ for (Expression tag: tags){
+ __scopeTags.emplace(scope, tag);
+ }
}
void
- CFGraph::addLink(unsigned int nodeFrom, unsigned int nodeTo) {
- __relations.insert(std::make_pair(nodeFrom, nodeTo));
+ 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 SymbolInvalid& symbol){
+ 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 SymbolPacked& nodeFrom, DFGConnection link) {
- if (!linkExists(nodeTo, nodeFrom))
- {
- __edges.emplace_back(nodeTo, nodeFrom);
- __data.push_back(link);
-
- EdgeId eid = __edges.size()-1;
- __outEdges.emplace(nodeFrom, eid);
- }
+ DFAGraph::addLink(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
+ VisitorAddLink visitor(this, nodeTo, link);
+ boost::apply_visitor(visitor, nodeFrom);
}
void
- DFAGraph::addTag(const SymbolPacked &node, Expression &&tag) {
- __tags.emplace(node, tag);
+ 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 9fb1f8f..85acd90 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,172 +1,200 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_H
-#include <string>
-#include <gringo/control.hh>
+
#include <ast.h>
-#include <QStringList>
+
+#include <gringo/control.hh>
+#include <string>
#include <climits>
+#include <boost/bimap.hpp>
#include <boost/optional.hpp>
+#include <list>
namespace xreate {
- class CFGraph {
+ typedef unsigned int ScopePacked;
+
+ class CFAGraph {
friend class ClaspLayer;
public:
- void addNode(unsigned int function, std::string &&tag);
- void addLink(unsigned int nodeFrom, unsigned int nodeTo);
- bool existsNode(unsigned int function) const;
- void print(std::ostream &cout) const;
+ 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<unsigned int, unsigned int> __relations;
- std::map<unsigned int, std::string> __nodes;
+ 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;
- unsigned int scope;
+ 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(const SymbolPacked& node, Expression&& tag);
- void addLink(const SymbolPacked& nodeTo, const SymbolPacked& nodeFrom, DFGConnection link);
+ 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 addCFAData(CFGraph &&graph);
+ 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);
+ ScopePacked pack(CodeScope* scope);
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
Symbol unpack(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::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<CodeScope*> __registryScopes;
void printWarnings(std::ostream& out);
bool onModel(Gringo::Model const &model);
- QStringList compile(const Expression &e) const;
- QStringList compileNeg(const Expression &e) const;
+ 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 addImports();
+ 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 1cc1e05..5f7bfbc 100644
--- a/cpp/src/instructions/instr-containers.cpp
+++ b/cpp/src/instructions/instr-containers.cpp
@@ -1,469 +1,470 @@
#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 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
//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
- PointerType* tyInt8P = PointerType::getInt8PtrTy(llvm::getGlobalContext());
- Value* nullInt8P = llvm::ConstantPointerNull::get(tyInt8P);
+
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);
- llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", 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(blockException);
-
- llvm->initExceptionsSupport();
- llvm::Function* fAllocate = llvm->module->getFunction("__cxa_allocate_exception");
- llvm::Function* fThrow = llvm->module->getFunction("__cxa_throw");
- auto exception = llvm->builder.CreateCall(fAllocate, ConstantInt::get(IntegerType::getInt64Ty(getGlobalContext()), 4));
- vector<Value*> throwParams{exception, nullInt8P, nullInt8P};
- llvm->builder.CreateCall(fThrow, ArrayRef<Value*>(throwParams));
- llvm->builder.CreateUnreachable();
-
-
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;
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);
// 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;
}
+llvm::Value*
+Instructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar){
+ EXPAND_CONTEXT
+ llvm::IRBuilder<>& builder = llvm->builder;
+
+
+ //builder.CreateSwitch()
+
+}
+
llvm::Value*
Instructions::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
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
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;
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::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;
};
}
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));
};
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
}
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
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);
};
}
if (linkedlist){
return index;
}
}
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);
}
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);
}
}
};
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);
}
}
diff --git a/cpp/src/instructions/instr-containers.h b/cpp/src/instructions/instr-containers.h
index be660d1..9465d35 100644
--- a/cpp/src/instructions/instr-containers.h
+++ b/cpp/src/instructions/instr-containers.h
@@ -1,85 +1,86 @@
#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H
#include "llvmlayer.h"
#include "ast.h"
#include <llvm/IR/Value.h>
#include <vector>
#include "pass/compilepass.h"
namespace xreate {
namespace containers {
class Iterator{
public :
virtual llvm::Value* begin() =0;
virtual llvm::Value* end() = 0;
virtual llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") = 0;
virtual llvm::Value* move(llvm::Value* index, const std::string& hintRetVar="")=0;
virtual ~Iterator(){};
static Iterator* create(CompilePass::Context context, const Symbol& var);
};
class Instructions {
public:
Instructions(CompilePass::Context ctx);
llvm::Value* compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string ident = "");
llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
llvm::Value*compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
+ llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
llvm::Value* compileConstantStringAsPChar(const string &data, const std::string& hintRetVar);
llvm::Value* compileConstantArray(const Expression &expr, const std::string& hintRetVar="");
private:
CompilePass::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif //CODEINSTRUCTIONS_H
/*
template<Operator Instruction>
struct InstructionClasses {};
template<>
struct InstructionClasses<Operator::LIST> {
typedef InstructionList Impl;
};
template<>
struct InstructionClasses<Operator::MAP> {
typedef InstructionMap Impl;
};
template<Operator Instruction>
class CodeInstruction: public InstructionClasses<Instruction>::Impl
{
typedef typename InstructionClasses<Instruction>::Impl InstructionImpl;
public:
CodeInstruction(CodeScope* parent)
: InstructionImpl(parent)
{}
llvm::Value *
compileExpression(const Expression &expr, LLVMLayer &l, const std::string * const hintRetVar)
{
if (expr.op == Instruction)
return InstructionImpl::compileDefault(expr, l, hintRetVar);
return CodeScope::compileExpression(expr, l, hintRetVar);
}
};
}
*/
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 47121d3..2afa47c 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,229 +1,249 @@
#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)
{
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/llvmlayer.h b/cpp/src/llvmlayer.h
index 3079d28..fbbc823 100644
--- a/cpp/src/llvmlayer.h
+++ b/cpp/src/llvmlayer.h
@@ -1,56 +1,58 @@
#ifndef LLVMLAYER_H
#define LLVMLAYER_H
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"
namespace xreate {
class AST;
class ExternLayer;
class TypeAnnotation;
class LLVMLayer {
public:
LLVMLayer(AST* rootAST);
AST *ast = 0;
ExternLayer *layerExtern =0;
llvm::Module *module = 0;
llvm::ExecutionEngine* jit= 0;
llvm::IRBuilder<> builder;
void moveToGarbage(void *o);
llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
void print();
void* getFunctionPointer(llvm::Function* function);
void initJit();
- void initExceptionsSupport();
+
+ llvm::BasicBlock* initExceptionBlock(llvm::BasicBlock* block);
private:
+ void initExceptionsSupport();
llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
std::vector<void *> __garbage;
};
struct TypeUtils {
bool isStruct(const Expanded<TypeAnnotation>& ty);
bool isPointer(const Expanded<TypeAnnotation>& ty);
std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
TypeUtils(LLVMLayer*llvmlayer)
: llvm(llvmlayer){}
private:
LLVMLayer* llvm;
};
}
#endif // LLVMLAYER_H
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 89e74ec..da48e1c 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,121 +1,123 @@
#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>
class AbstractPass: public AbstractPassBase {
private:
std::set<Symbol> __visitedSymbols;
+ Output __defaultValue;
public:
- AbstractPass(PassManager* manager): AbstractPassBase(manager) {}
+ AbstractPass(PassManager* manager, Output defaultValue=Output())
+ : AbstractPassBase(manager), __defaultValue(defaultValue) {}
//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());
+
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
- assert(expression.op != Operator::MAP || expression.op == Operator::MAP && expression.blocks.size());
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
- /*
if (expression.op == Operator::CALL) {
const std::string &calleeName = expression.getValueString();
- ManagedFnPtr callee = root->findFunction(calleeName);
+ ManagedFnPtr callee = man->root->findFunction(calleeName);
+ if (callee) processFnCall(callee, context);
}
- */
break;
case Expression::IDENT:
assert(context.scope);
std::string ident = expression.getValueString();
const Symbol& symbol = context.scope->findSymbol(ident);
- if (__visitedSymbols.count(symbol)) {break;}
+ if (__visitedSymbols.count(symbol)) {assert(false && "Invalid state");}
__visitedSymbols.insert(symbol);
PassContext context2 = context;
context2.scope = symbol.scope;
if (CodeScope::hasDeclaration(symbol)) {
- process(CodeScope::findDeclaration(symbol), context2, ident);
+ return process(CodeScope::findDeclaration(symbol), context2, ident);
}
break;
}
}
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;
}
}
};
}
#endif
diff --git a/cpp/src/pass/cfgpass.cpp b/cpp/src/pass/cfgpass.cpp
index c3195e7..6c84981 100644
--- a/cpp/src/pass/cfgpass.cpp
+++ b/cpp/src/pass/cfgpass.cpp
@@ -1,41 +1,73 @@
#include "cfgpass.h"
-#include <QString>
-
+#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate;
+
void
-CFGPass::start()
-{
- __context.graph = CFGraph();
+CFGPass::initSignatures(){
+ auto range = man->root->__interfacesData.equal_range(CFA);
+ for (auto i = range.first; i!= range.second; ++i){
+ __signatures.emplace(i->second.op, i->second);
+ }
+}
+
+void CFGPass::run(){
+ initSignatures();
+
+ return AbstractPass::run();
}
void
CFGPass::finish()
{
- man->clasp->addCFGData(move(__context.graph));
+ man->clasp->setCFAData(move(__context.graph));
+
+ return AbstractPass::finish();
}
-CFGPass::CFGPass(PassManager* manager)
- : ASTPass(manager)
+void
+CFGPass::processFnCall(ManagedFnPtr function, PassContext context)
{
- man->registerFilter(this, PassFilter:: FUNCTION);
- man->registerFilter(this, PassFilter:: FUNCTIONCALL);
+ ClaspLayer* clasp = man->clasp;
+ __context.graph.addLink(clasp->pack(context.scope), function->getName());
+
+ return AbstractPass::processFnCall(function, context);
+}
+
+void
+CFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
+ return AbstractPass::process(scope, context, hintBlockDecl);
+}
+
+void
+CFGPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
+ ClaspLayer* clasp = man->clasp;
+
+ if (expression.__state == Expression::COMPOUND){
+ Operator op= expression.op;
+
+ if (__signatures.count(op)) {
+ assert(expression.blocks.size());
+
+ for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
+ __context.graph.addScopeNodeTags(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
+ }
+ }
+ }
+
+ return AbstractPass::process(expression, context, varDecl);
}
void
-CFGPass::process(ManagedFnPtr function, PassContext context)
+CFGPass::process(ManagedFnPtr function)
{
- //FUNCTION decl
- if (context.function == function)
- {
- const string& name = function->getName();
-
- __context.graph.addNode(function.id(), string(name));
- return;
- }
-
- //FUNCTIONCALL decl
- __context.graph.addLink(context.function.id(), function.id());
-}
\ No newline at end of file
+ __context.graph.addFunctionNodeTags(function->getName(), function->getAnnotations());
+
+ return AbstractPass::process(function);
+}
+
+CFGPass::CFGPass(PassManager* manager)
+ : AbstractPass(manager)
+{}
diff --git a/cpp/src/pass/cfgpass.h b/cpp/src/pass/cfgpass.h
index 0eb3ebf..c68ba2f 100644
--- a/cpp/src/pass/cfgpass.h
+++ b/cpp/src/pass/cfgpass.h
@@ -1,26 +1,33 @@
// Control Flow Graph determination pass
#ifndef CFGPASS_H
#define CFGPASS_H
#include "passmanager.h"
#include "clasplayer.h"
+#include "abstractpass.h"
namespace xreate {
-class CFGPass : public ASTPass
+class CFGPass : public AbstractPass<void>
{
public:
- void init();
+ void process(ManagedFnPtr function) override;
+ void processFnCall(ManagedFnPtr function, PassContext context) override;
+ void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
+ void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
+
CFGPass(PassManager* manager);
- void process(ManagedFnPtr function, PassContext context);
- virtual void start();
- virtual void finish();
+ void finish() override;
+ void run() override;
private:
struct {
- CFGraph graph;
+ CFAGraph graph;
} __context;
+ std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
+
+ void initSignatures();
}; }
#endif // CFGPASS_H
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index e374bc8..ed0d8b2 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,449 +1,454 @@
#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){
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);
};
};
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"));
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 9026b78..197541f 100644
--- a/cpp/src/pass/dfgpass.cpp
+++ b/cpp/src/pass/dfgpass.cpp
@@ -1,152 +1,184 @@
#include "dfgpass.h"
-#include "../passmanager.h"
-
+#include "passmanager.h"
+#include "clasplayer.h"
+#include <boost/format.hpp>
using namespace xreate;
using namespace std;
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);
-SymbolPackedOptional
+ } 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);
+ }
+}
+
+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) {
- SymbolPacked nodeThis = clasp->pack(context.scope->findSymbol(decl), decl);
+ SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), decl);
__context.graph.addTag(nodeThis, Expression(tag.second));
}
}
switch(expression.__state) {
case Expression::IDENT:
- AbstractPass::process(expression, context, decl);
-
- string ident = expression.getValueString();
- const Symbol& identSymbol = context.scope->findSymbol(ident);
+ const string& ident = expression.getValueString();
+ SymbolNode nodeFrom = AbstractPass::process(expression, context, decl);
+ SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident));
- SymbolPacked nodeFrom = clasp->pack(identSymbol);
- if (!decl.empty()) {
- SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl));
- __context.graph.addLink(move(nodeTo), move(nodeFrom), DFGConnection::ALIAS);
- }
+ __context.graph.addLink(nodeTo, nodeFrom, DFGConnection::ALIAS);
+ return nodeTo;
+ }
- return nodeFrom;
+ //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<SymbolPackedOptional> operands;
+ 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 boost::none;
+ if (!function) return SymbolInvalid();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
- std::vector<SymbolPackedOptional>::iterator op = operands.begin();
+ std::vector<SymbolNode>::iterator op = operands.begin();
for (const std::string &arg: scopeRemote->__args) {
- if (*op) {
const Symbol &nodeRemote = scopeRemote->findSymbol(arg);
- __context.graph.addLink(clasp->pack(nodeRemote), **op, DFGConnection::OPT);
- }
+ SymbolPacked* operandPacked = boost::get<SymbolPacked>(&*op);
+ assert(operandPacked);
+ __context.graph.addLink(clasp->pack(nodeRemote), *operandPacked, DFGConnection::OPT);
++op;
}
- SymbolPacked ret = clasp->pack(Symbol{0, scopeRemote});
- if (!decl.empty()) {
- __context.graph.addLink(
- clasp->pack(
- context.scope->findSymbol(decl)),
- ret, DFGConnection::OPT);
- }
-
- return ret;
+ //TODO need SymbolTransient::connection mark in order to represent OPT connection
+ return clasp->pack(Symbol{0, scopeRemote});
}
}
- std::vector<SymbolPackedOptional> operands;
+ std::vector<SymbolNode> operands;
+
+ if (expression.__state != Expression::COMPOUND){
+ AbstractPass::process(expression, context, decl);
+ return SymbolInvalid();
+ }
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<SymbolPackedOptional>::const_iterator arg = operands.begin();
+ std::vector<SymbolNode>::iterator arg = operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
- if (*arg && tag->__state != Expression::INVALID) {
- __context.graph.addTag(**arg, Expression(*tag));
+ if (tag->__state != Expression::INVALID) {
+ __context.graph.addTag(*arg, Expression(*tag));
}
++arg; ++tag;
}
Expression retTag = *scheme.getOperands().begin();
if (retTag.__state != Expression::INVALID) {
- assert(!decl.empty());
- SymbolPacked pdecl = clasp->pack(context.scope->findSymbol(decl));
- __context.graph.addTag(pdecl, move(retTag));
+ return SymbolTransient{{retTag}};
}
}
// adhoc for MAP case, TODO reorganize code in more clear manner
if (expression.op == Operator::MAP) {
- SymbolPackedOptional nodeFrom;
+ SymbolNode nodeFrom;
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));
- __context.graph.addLink(move(nodeTo), move(*nodeFrom), DFGConnection::PROTO);
+ 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 boost::none;
+ return SymbolInvalid();
}
- AbstractPass::process(expression, context, decl);
- return boost::none;
+ return SymbolInvalid();
}
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));
}
diff --git a/cpp/src/pass/dfgpass.h b/cpp/src/pass/dfgpass.h
index 8622130..fcf9cf1 100644
--- a/cpp/src/pass/dfgpass.h
+++ b/cpp/src/pass/dfgpass.h
@@ -1,34 +1,34 @@
// Data Flow Graph determination pass
#ifndef DFGPASS_H
#define DFGPASS_H
#include "abstractpass.h"
#include "clasplayer.h"
-#include <boost/optional.hpp>
namespace xreate {
-typedef boost::optional<SymbolPacked> SymbolPackedOptional;
-class DFGPass : public AbstractPass<SymbolPackedOptional> {
+class ClaspLayer;
+
+class DFGPass : public AbstractPass<SymbolNode> {
public:
- SymbolPackedOptional process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
+ SymbolNode process(ManagedFnPtr function);
+ SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
DFGPass(PassManager* manager);
- unsigned int hash(const CodeScope* scope);
void init();
void run();
void finish();
private:
struct
{
DFAGraph graph;
} __context;
std::map<Operator, Expression> __signatures; //DFA data for particular operators
ClaspLayer* clasp;
};
};
#endif
diff --git a/cpp/src/pass/functiontagspass.cpp b/cpp/src/pass/functiontagspass.cpp
deleted file mode 100644
index 6c30b77..0000000
--- a/cpp/src/pass/functiontagspass.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#include "functiontagspass.h"
-using namespace std;
-using namespace xreate;
-
-void
-FunctionTagsPass::process(ManagedFnPtr function)
-{
- man->clasp->addFunctionTags(function->getName(), function->getAnnotations());
-}
diff --git a/cpp/src/pass/functiontagspass.h b/cpp/src/pass/functiontagspass.h
deleted file mode 100644
index 5d92786..0000000
--- a/cpp/src/pass/functiontagspass.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef FUNCTIONTAGSPASS_H
-#define FUNCTIONTAGSPASS_H
-
-#include "abstractpass.h"
-
-namespace xreate {
-class FunctionTagsPass: public AbstractPass<void>
-{
-public:
- FunctionTagsPass(PassManager *manager): AbstractPass<void>(manager) {}
- void process(ManagedFnPtr function) override;
-};}
-
-#endif // FUNCTIONTAGSPASS_H
diff --git a/cpp/src/passmanager.cpp b/cpp/src/passmanager.cpp
index 37c3f28..3bcfded 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager.cpp
@@ -1,84 +1,93 @@
#include <pass/abstractpass.h>
#include "query/containers.h"
#include "passmanager.h"
#include "pass/compilepass.h"
#include "Parser.h"
+#include "pass/cfgpass.h"
#include "pass/dfgpass.h"
-#include "pass/functiontagspass.h"
#include "pass/logging.h"
+#include <list>
using namespace xreate;
using namespace std;
PassManager*
PassManager::prepareForCode(std::string&& code){
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
return prepareForCode(scanner);
}
PassManager*
PassManager::prepareForCode(Scanner& scanner){
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager* man = new PassManager;
AST* ast = new AST(parser.root);
man->root = ast;
man->clasp = new ClaspLayer();
man->clasp->ast = man->root;
man->llvm = new LLVMLayer(man->root);
- man->registerPass(new DFGPass(man));
- man->registerPass(new FunctionTagsPass(man));
+
+ CFGPass* passCFG = new CFGPass(man);
+
+ man->registerPass(new DFGPass(man), passCFG);
+ man->registerPass(passCFG);
return man;
}
void
-PassManager::registerPass(AbstractPassBase* pass)
+PassManager::registerPass(AbstractPassBase* pass, AbstractPassBase* parent)
{
- __passes.push_back(pass);
+ __passes.emplace(parent, pass);
}
void*
PassManager::run()
{
- for (AbstractPassBase* pass: __passes)
- {
- pass->run();
- pass->finish();
- }
-
- clasp->registerdQuery(new containers::Query());
- clasp->run();
+ runWithoutCompilation();
CompilePass* compiler = new CompilePass(this);
compiler->run();
//Compiler Dependents:
Logging* logger = new Logging(this);
logger->initDependencies(compiler);
logger->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
void PassManager::runWithoutCompilation(){
- for (AbstractPassBase* pass: __passes)
- {
- pass->run();
- pass->finish();
- }
+ std::list<AbstractPassBase*> passes{nullptr};
+ while (passes.size()){
+ AbstractPassBase* parent = passes.front();
+
+ auto range = __passes.equal_range(parent);
+
+ for (auto i=range.first; i!=range.second; ++i){
+ AbstractPassBase* pass = i->second;
+
+ pass->run();
+ pass->finish();
+
+ passes.push_back(pass);
+ }
+
+ passes.pop_front();
+ }
clasp->registerdQuery(new containers::Query());
clasp->run();
}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index e9d581c..4c9e0de 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,31 +1,33 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
-#include "clasplayer.h"
-#include "ast.h"
-#include <set>
#include "Scanner.h"
+#include <string>
+#include <map>
namespace xreate {
class AbstractPassBase;
+class ClaspLayer;
+class LLVMLayer;
+class AST;
class PassManager
{
public:
~PassManager();
void* run();
void runWithoutCompilation();
- void registerPass(AbstractPassBase* pass);
+ void registerPass(AbstractPassBase* pass, AbstractPassBase* prerequisite=nullptr);
static PassManager* prepareForCode(std::string&& code);
static PassManager* prepareForCode(Scanner& scanner);
ClaspLayer* clasp;
LLVMLayer* llvm;
AST* root;
private:
//typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
//FILTERS_STORAGE __filters;
- std::list<AbstractPassBase* > __passes;
+ std::multimap<AbstractPassBase*, AbstractPassBase*> __passes;
}; }
#endif
diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h
index 6da2c5e..663b08c 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,80 +1,83 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
+
#include "passmanager.h"
+#include "clasplayer.h"
+
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
const ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index 532b46d..925023c 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,128 +1,130 @@
#ifndef UTILS_H
#define UTILS_H
#include "jeayeson/jeayeson.hpp"
//TODO mark dirty members
/*
template<class T>
struct DdesctructableClass<T> {
}
*/
/*
template<class OriginalType>
struct TagUpdatable{
TagUpdatable(const OriginalType& source)
: __source(source)
{}
TagUpdatable() = delete;
const OriginalType& __source;
};
struct Updatable;
template <class Tag, class OT>
struct TagsDictionary
{};
template<class OT>
struct TagsDictionary<Updatable, OT>
{
typedef TagUpdatable<OT> TagName;
};
template<class Tag, class OT>
struct awareOf
{
awareOf(OT& dest)
: __dest(dest)
{}
awareOf<Tag, OT>&
operator= (const typename TagsDictionary<Tag, OT>::TagName& source)
{
__dest = source.__source;
}
private:
OT& __dest;
};
template<class Tag<OT>>
const OT&
awareOf(const Tag<OT>& holder)
{
return std::forward<OT>(holder.__source);
}
*/
namespace xreate {
template<class Tag, class Source>
struct AddTag {
explicit
AddTag(const Source &&src)
: __src(src) { }
operator const Source&() const{
return __src;
}
const Source& get() const{
return __src;
}
const Source*
operator->() const {
return &__src;
}
private:
Source __src;
};
struct Expand_t{};
template<class Source>
using Expanded = AddTag<Expand_t, Source>;
-
+
+
+ //DEBT move to resources compiler. https://github.com/markusfisch/cpprc
class Config {
private:
json_map __storage;
static Config __self;
Config();
public:
static std::string get(std::string key) {
return __self.__storage.get_for_path<json_value>(key).get<std::string>();
}
};
}
#define RST "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
#define FRED(x) KRED << x << RST
#define FGRN(x) KGRN <<x << RST
#define FYEL(x) KYEL << x << RST
#define FBLU(x) KBLU << x << RST
#define FMAG(x) KMAG x RST
#define FCYN(x) KCYN x RST
#define FWHT(x) KWHT x RST
#define BOLD(x) "\x1B[1m" x RST
#define UNDL(x) "\x1B[4m" x RST
#endif // UTILS_H
diff --git a/cpp/tests/CFGtests.cpp b/cpp/tests/CFGtests.cpp
new file mode 100644
index 0000000..44e92ef
--- /dev/null
+++ b/cpp/tests/CFGtests.cpp
@@ -0,0 +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");
+ int countNoneValue = 0;
+ if (answer)
+ countNoneValue = std::distance(answer->first, answer->second);
+ EXPECT_EQ(1, countNoneValue);
+
+ answer = man->clasp->query("annotationF2");
+ countNoneValue = 0;
+ if (answer)
+ countNoneValue = std::distance(answer->first, answer->second);
+ EXPECT_EQ(1, countNoneValue);
+}
+
+TEST(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
new file mode 100644
index 0000000..fd82f58
--- /dev/null
+++ b/cpp/tests/DFGtests.cpp
@@ -0,0 +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"));
+
+ 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 3addb1b..2929080 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,27 +1,41 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
-#include "pass/functiontagspass.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) {
+ 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());
+}
+
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 15b4e11..4c149bc 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,58 +1,57 @@
/*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
-#include "pass/functiontagspass.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));
+ 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/externc.cpp b/cpp/tests/externc.cpp
index fe5587e..ae6287a 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,105 +1,104 @@
#include "gtest/gtest.h"
#include "passmanager.h"
-#include "pass/functiontagspass.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));
}
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{return arc4random() }";
+ "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/skipdetection.cpp b/cpp/tests/skipdetection.cpp
new file mode 100644
index 0000000..5ccb14b
--- /dev/null
+++ b/cpp/tests/skipdetection.cpp
@@ -0,0 +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"));
+ 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 8826b37..9cb9a5c 100644
--- a/cpp/tests/testBasic.cpp
+++ b/cpp/tests/testBasic.cpp
@@ -1,27 +1,26 @@
#include "gtest/gtest.h"
#include "passmanager.h"
-#include "pass/functiontagspass.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
using namespace xreate;
TEST(EntryFunction, test1){
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 d426cf1..15bcd61 100644
--- a/cpp/tests/testClangAPI.cpp
+++ b/cpp/tests/testClangAPI.cpp
@@ -1,191 +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 "/private/prg/vendors/clang/lib/CodeGen/CodeGenTypes.h"
-#include "/private/prg/vendors/clang/lib/CodeGen/CodeGenModule.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 <QString>
+#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.7/bin/../lib/clang/3.7.0/include"
- ,"-I/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include"
- ,"-I/usr/include/x86_64-linux-gnu"
+ ,"-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 = QString("#include \"%1\"").arg("libxml/tree.h").toStdString();
+ 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*";
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 = QString("#include \"%1\"").arg("bsd/stdlib.h").toStdString();
+ 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/testLogging.cpp b/cpp/tests/testLogging.cpp
index 1d6de19..a84026a 100644
--- a/cpp/tests/testLogging.cpp
+++ b/cpp/tests/testLogging.cpp
@@ -1,87 +1,87 @@
/*
* testLogging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"
#include "pass/compilepass.h"
#include "pass/logging.h"
using namespace std;
using namespace xreate;
TEST(Logging, simpleInjection){
PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");
man->runWithoutCompilation();
CompilePass* compilator = new CompilePass(man);
compilator->run();
CompilePass::FunctionUnit* fTest = compilator->getFunctionUnit(CompilePass::FunctionQuery("test"));
ASSERT_NE(fTest, nullptr);
CompilePass::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
CodeScope* scopeTest = scopeUnitTest->scope;
Symbol symbX = scopeTest->findSymbol("x");
TypeAnnotation typX = scopeTest->findDefinition(symbX);
llvm::Value* retRaw = scopeUnitTest->compile();
llvm::BasicBlock& blockTestRaw = fTest->raw->getEntryBlock();
LLVMLayer* llvm = man->llvm;
//llvm->builder.SetInsertPoint(&blockTestRaw);
CompilePass::Context params{fTest, scopeUnitTest, compilator};
Logging l(man);
l.inject(symbX, params);
llvm->initJit();
int (*f)() = (int(*)()) llvm->getFunctionPointer(fTest->raw);
testing::internal::CaptureStdout();
f();
std::string&& output = testing::internal::GetCapturedStdout();
EXPECT_STREQ("10\n", output.c_str());
}
TEST(Logging, simpleInjection2){
- PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int; logging. return x}");
+ PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int; logging. x}");
man->runWithoutCompilation();
CompilePass* compiler= new CompilePass(man);
compiler->run();
Logging* logger = new Logging(man);
logger->initDependencies(compiler);
logger->run();
man->llvm->initJit();
man->llvm->print();
int (*f)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction());
testing::internal::CaptureStdout();
f();
std::string&& output = testing::internal::GetCapturedStdout();
EXPECT_STREQ("10\n", output.c_str());
}
TEST(Logging, simpleInjection3){
FILE* input = fopen("scripts/cases/log.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();
fclose(input);
}
diff --git a/scripts/cases/log.xreate b/scripts/cases/log.xreate
index 1bb0ac9..997edf1 100644
--- a/scripts/cases/log.xreate
+++ b/scripts/cases/log.xreate
@@ -1,64 +1,64 @@
/*
Log level:
Log entry(flat, hierarchical)
*/
// EXTERN INCLUDES
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["libxml/tree.h", "string.h"]
}.
}
// CONTAINERS
interface(dfa) {
operator map:: (op(seqaccess)) -> impl(solid).
operator list_range:: ()->impl(on_the_fly).
operator list:: ()->impl(solid).
operator fold:: (op(seqaccess)).
operator index:: (op(randaccess)).
/* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
}
import raw("core/containers.lp").
// PROGRAM
XmlNode = type alias {
tag:: string,
/* attrs:: [string],*/
content:: string
}.
Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
XmlTree = type alias Tree(XmlNode).
test= function():: num; entry {
filename = "project/documentation.fodt" :: string.
docRaw = xmlParseFile(filename) :: xmlDocPtr.
tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
childrenRaw = tree["children"]:: [xmlNodePtr]; containers:linkedlist(next, null).
size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int):: int {
// $log{
// count +1:: warning, subsystem=xml
// }
-
+
//log{warning, subsystem=xml, ..}
childName = child["name"]::string; logging.
count + strlen(childName):: int
}.
size
}
diff --git a/scripts/input.xreate b/scripts/input.xreate
index ccb0330..bb95705 100644
--- a/scripts/input.xreate
+++ b/scripts/input.xreate
@@ -1,92 +1,106 @@
/* 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"]
+ 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].
-test= function():: num; entry {
+
+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.
- childrenRaw = tree["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
- size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int) : int {
- count +1
+
+ 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).
}.
- size
+ 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
}
*/
-/*
-query = function (tree:: XmlTree):: [string, string]
-{
- children = switch :: context(children)
- case default
- { [] }
-
- case tree[0]:: NeedChildren(childrenFilters); ApplyTransform(transFilters)
- {
- loop fold (tree[1]->child:: Tree(Leaf) | childrenFilters, null->accum:: [Tree(Leaf)])
- :: [Tree(Leaf)]
- {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
- {null}.
-
- node + children
-}
-*/
+
+

Event Timeline