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