Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2731294
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:33 AM
Size
242 KB
Mime Type
text/x-diff
Expires
Mon, Mar 16, 4:33 AM (1 d, 18 h)
Engine
blob
Format
Raw Data
Handle
243935
Attached To
rXR Xreate
View Options
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index 6574680..c24f5bc 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,454 +1,515 @@
//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;
+ return xkind == _assign && (y->kind == _function || y->kind == _pre);
}
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".
+ pre = "pre".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
+ lcurbrack = '{'.
+ rcurbrack = '}'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
+ context = "context".
tagcolon = "::".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
-Xreate = { ( RuleDecl | InterfaceData | Imprt | IF(checkFuncDecl()) FDecl | TDecl ) }.
+Xreate = (. Function* function; .)
+{ ( RuleDecl | InterfaceData | Imprt | ContextSection
+ | IF(checkFuncDecl()) FDecl<function> (. root.add(function); .)
+ | 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)); .)
+
+FDecl<Function* &f> = (. std::wstring fname; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; .)
+Ident<fname> assign
+[pre (. flagIsPrefunct = true; .)]
+function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .)
+
+['(' 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); .)
+} ')']
+
+[ tagcolon
+( IF(flagIsPrefunct) FnTag<f>
+ | Type<typOut> (. f->setReturnType(typOut); .)
+)
+{';' FnTag<f> }]
+BDecl<entry> (. entry->__body.bindType(move(typOut));.)
.
+ContextSection<>= (. std::wstring context; Function* f; .)
+"case" "context" tagcolon Ident<context>
+lcurbrack { FDecl<f> (. root.add(f, context); .)
+} rcurbrack.
+
/**
* TYPES
*
*/
TypeTerm<TypeAtom& typ> = (. std::wstring tid; .)
("string" | "int" | "num" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .)
.
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
| TypeTerm<typ3> (. typ = TypeAnnotation(typ3); .)
|IF (checkIndex()) Ident<tid> lbrack
Ident<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> (. typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
} rbrack
| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
['(' Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
{',' Type<typ2> (. typ.__operands.push_back(typ2); .)
} ')']
) .
TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
'[' Type<ty> (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .)
{',' Type<ty> (. typ.__operator = TypeOperator::TUPLE; typ.__operands.push_back(ty); .)
}']'
.
TStruct<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring field; .)
'{'
Ident<field> tagcolon Type<t> (. typ = TypeAnnotation(TypeOperator::STRUCT, {t}); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> tagcolon Type<t>} (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
'}'.
- TDecl = (. std::wstring ttag; TypeAnnotation t; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
+ TDecl = (. std::wstring ttag; TypeAnnotation t, t1; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
Ident<tname> assign "type"
(
"alias" Type<t> (. root.add(move(t), Atom<Identifier_t>(tname)); .)
+ | "variant" lparen Ident<arg> (. t = TypeAnnotation(TypeOperator::VARIANT, {}); args.push_back(Atom<Identifier_t>(arg)); .)
+ {',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
+ } rparen (. t.addFields(move(args)); root.add(move(t), Atom<Identifier_t>(tname)); .)
+
| 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)); .)
.
+ContextDecl<CodeScope * scope> = (. Expression tag; .)
+context tagcolon
+MetaSimpExpr<tag> (. scope->tags.push_back(move(tag)); .)
+{';' MetaSimpExpr<tag> (. scope->tags.push_back(move(tag)); .)
+}.
+
+//TODO forbid multiple body declaration (ExprTyped)
BDecl<CodeScope* scope> = (. Expression body; TypeAnnotation typ; pushContextScope(scope); .)
-'{' { (
- IF(checkAssignment()) VDecl<scope> '.'
- | ExprTyped<body, typ> (. scope->setBody(body);.)
-)} (. popContextScope(); .)
-'}'.
+'{' { (RuleContextDecl<scope> | ContextDecl<scope> '.'
+ | IF(checkAssignment()) VDecl<scope> '.'
+ | ExprTyped<body, typ> (. scope->setBody(body); popContextScope();.)
+)} '}'.
IfDecl<Expression& e, TypeAnnotation typ> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(context.scope)); TypeAnnotation typIf; .)
"if" '(' Expr<cond> ')' tagcolon Type<typIf> BDecl<&*blockTrue> "else" BDecl<&*blockFalse>
(. e = Expression(Operator::IF, {cond}); e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e, TypeAnnotation& typOut> =
- (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc; TypeAnnotation typEl, typAcc;
+ (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; TypeAnnotation typEl, typAcc;
ManagedScpPtr block = root.add(new xreate::CodeScope(context.scope)); .)
"loop"
("map" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ')' tagcolon Type<typOut> BDecl<&*block>
(. e = Expression(Operator::MAP, {eIn});
e.addBindings({Atom<Identifier_t>(varEl)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
e.addBlock(block); .)
|"fold" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc> tagcolon Type<typAcc> ')' tagcolon Type<typOut> BDecl<&*block>
(. e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
block->addArg(Atom<Identifier_t>(varAcc), move(typAcc));
e.addBlock(block);
.)
+
+ | "context" '(' string (. contextClass = t->val; .)
+ ')' BDecl<&*block>
+ (. e = Expression(Operator::LOOP_CONTEXT, {Expression(Atom<String_t>(std::move(contextClass)))});
+ e.addBlock(block);
+ .)
).
-SwitchDecl<Expression& eSwitch> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); .)
- // ["switch" [tagcolon Type<typ> {';' MetaSimpExpr<tag>}]]
+SwitchDecl<Expression& eSwitch> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.)
+["switch"
+ ("ad" "hoc" lparen Expr<eCondition> tagcolon MetaSimpExpr<tag> rparen (. eSwitch.op = Operator::SWITCH_ADHOC; eSwitch.operands.push_back(eCondition); eSwitch.tags.emplace(tag.getValueString(), move(tag)); .)
+ | lparen Expr<eCondition> rparen tagcolon Type<typ> (. eSwitch.operands.push_back(eCondition); eSwitch.type = typ; .)
+ )
+]
CaseDecl<eSwitch> {CaseDecl<eSwitch>}
.
-CaseDecl<Expression& outer> = (. Expression inner(Operator::CASE, {});
- ManagedScpPtr scopeCond = root.add(new xreate::CodeScope(context.scope));
- ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scopeCond)); .)
+CaseDecl<Expression& outer> = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); .)
"case"
- ( "default"
- | CaseParams<&*scopeCond>
- )
+ ( "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
+ exprCase.addBlock(scope);
+ outer.operands.insert(++outer.operands.begin(), exprCase); .)
- BDecl<&*scopeBody> (. inner.addBlock(scopeCond); inner.addBlock(scopeBody); outer.addArg(move(inner)); .)
-.
+ | CaseParams<&*scope> (. ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scope)); .)
+ BDecl<&*scopeBody> (. Expression exprCase(Operator::CASE, {});
+ exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .)
+ ).
CaseParams<CodeScope* scope> = (. Expression e; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
CaseParam<scope, guard>
- {',' 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()); .)
-')' '.' .
+"import" "raw" lparen string (. root.__rawImports.push_back(Atom<String_t>(t->val).get()); .)
+rparen .
InterfaceData<> = "interface" '('
( "dfa" ')' InterfaceDFA
| "extern-c" ')' InterfaceExternC
| "cfa" ')' InterfaceCFA
- ).
-
+ | "adhoc" ')' InterfaceAdhoc
+
+ ).
+
+InterfaceAdhoc<> =
+ '{' [ PrefunctionSchemeDecl ] '}'.
+
+PrefunctionSchemeDecl<> = (. TypeAnnotation typReturn; std::wstring prefName; Expression exprCases; .)
+ pre function Ident<prefName> tagcolon Type<typReturn>
+ '{' SwitchDecl<exprCases> '}'
+ (. Expression prefData(Operator::CALL, {Atom<Identifier_t>(prefName), exprCases});
+ prefData.type = typReturn;
+ root.addInterfaceData(Adhoc, move(prefData));
+ .).
+
+
InterfaceExternC<> = (.xreate::ExternData data; .)
'{' {IncludeExternDecl<data> | LibExternDecl<data> } '}'
(. root.addExternData(move(data)); .)
.
LibExternDecl<xreate::ExternData& data> = (. std::wstring pkgname, libname; .)
Ident<libname> assign "library" tagcolon "pkgconfig"
'(' string (. pkgname = t->val; .)
')' '.' (. data.addLibrary(Atom<Identifier_t>(libname), Atom<String_t>(pkgname)); .)
.
IncludeExternDecl<xreate::ExternData& data> = (. Expression inc; .)
"include" StructLiteral<inc> '.' (. data.addIncludeDecl(move(inc)); .)
.
InterfaceDFA<> = '{' { InstructDecl } '}' .
InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
"operator" InstructAlias<op> tagcolon '(' (.scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] ')' [ implic MetaSimpExpr<tag> (. tags[0] = tag; .)
] (. root.addDFAData(move(scheme)); .)
'.'.
InstructAlias<Operator& op> =
(
"map" (. op = Operator::MAP; .)
| "list_range" (. op = Operator::LIST_RANGE; .)
| "list" (. op = Operator::LIST; .)
| "fold" (. op = Operator::FOLD; .)
| "index" (. op = Operator::INDEX; .)
).
InterfaceCFA<> = '{' { InstructCFADecl } '}' .
InstructCFADecl<> = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands; .)
"operator" InstructAlias<op> tagcolon (. scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] '.' (. root.addInterfaceData(CFA, move(scheme)); .).
/*============================ METAPROGRAMMING ===============================*/
// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
// }.
FnTag<Function* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
MetaSimpExpr<tag>
['-' TagMod<mod>] (. f->addTag(std::move(tag), mod); .).
TagMod<TagModifier& mod> =
( "assert" (. mod = TagModifier::ASSERT; .)
| "require" (. mod = TagModifier::REQUIRE; .)
).
RuleDecl<> =
"rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
'(' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
{',' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
} ')'
["case" RGuard<guards> {',' RGuard<guards>}]
'{' RBody<args, guards> '}' .
+/* - TODO use RGuard for guards-*/
+RuleContextDecl<CodeScope* scope> = (.Expression eHead, eGuards, eBody; .)
+"rule" "context" tagcolon MetaSimpExpr<eHead>
+"case" MetaSimpExpr<eGuards>
+'{' MetaSimpExpr<eBody> '}' (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .).
+
Domain<DomainAnnotation& dom> =
(
"function" (. dom = DomainAnnotation::FUNCTION; .)
| "variable" (. dom = DomainAnnotation::VARIABLE; .)
).
RGuard<RuleGuards& guards>= (. Expression e; .)
MetaExpr<e> (. guards.add(std::move(e)); .).
MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
MetaExpr2<e>
[MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
].
MetaExpr2<Expression& e>=
(
'(' MetaExpr<e> ')'
| MetaSimpExpr<e>
).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
'(' [ 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 ===============================*/
+ /*============================ 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)); .)
+ | Ident< name> (. e = Expression(Atom<Identifier_t>(name)); root.recognizeVariantIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
| LoopDecl<e, typ>
| IfDecl<e, typ>
| SwitchDecl<e>
+ | AdhocDecl<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); .)
) ] ']'.
+AdhocDecl<Expression& e> = (. Expression command; .)
+"ad" "hoc" Expr<command> (. e.setOp(Operator::ADHOC); e.addArg(std::move(command)); .).
+
CalleeParams<Expression& e> = (. Expression e2; TypeAnnotation typ; .)
ExprTyped<e2, typ> (. e.addArg(std::move(e2)); .)
{',' ExprTyped<e2, typ> (. e.addArg(std::move(e2)); .)
}.
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| '<' (. op = Operator::LSS; .)
| '>' (. op = Operator::GTR; .)
).
END Xreate.
diff --git a/config/default.json b/config/default.json
index 7d03a30..ef2aff4 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,54 +1,56 @@
{
"containers": {
"id": {
"implementations": "impl_fulfill_cluster",
"clusters": "var_cluster",
"prototypes": "proto_cluster",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
"onthefly": "on_the_fly"
}
},
"logging": {
"id": "logging"
},
"function-entry": "entry",
"clasp": {
"bindings" : {
"variable": "bind",
"function": "bind_func",
- "scope": "bind_scope"
+ "scope": "bind_scope",
+ "scope_weak" : "bind_scope_weak"
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
- "template": "default",
+ "template": "adhocs",
"templates": {
- "basic": "EntryFunction*",
+ "basic": "EntryFunction*",
"default": "*-",
"types": "Types*-",
"containers": "Containers*-",
"ast": "AST*",
"non-containers": "*-Containers*",
"log": "Logging*",
- "clang": "ClangAPI*"
+ "clang": "ClangAPI*",
"cfg": "CFG.*",
"skip": "SkipDetection*",
"raw-xml": "libxml2*",
- "xml": "Xml.*"
+ "xml": "Xml.*",
+ "adhocs": "ExpressionSerializer.*:Adhoc.*:Context.*"
}
}
}
diff --git a/core/control-context.lp b/core/control-context.lp
new file mode 100644
index 0000000..1c27c0f
--- /dev/null
+++ b/core/control-context.lp
@@ -0,0 +1,27 @@
+%TODO context-dependent function specialization implemenetation(inline/...)
+
+ % context propagation
+
+bind_scope_demand(Scope, Context):- bind_scope_demand(ScopeChild, Context), cfa_parent(ScopeChild, scope(Scope)).
+bind_scope_demand(Scope, Context):- bind_function_demand(FnChild, Context), cfa_call(Scope, FnChild).
+bind_function_demand(Fn, Context):- bind_scope_demand(ScopeChild, Context), cfa_parent(ScopeChild, function(Fn)).
+
+bind_scope(Scope, Context) :- bind_scope(ScopeParent, Context), cfa_parent(Scope, scope(ScopeParent)).
+bind_scope(Scope, Context) :- bind_scope(ScopeParent, Context): cfa_call(ScopeParent, FnCurrent); cfa_call(_, FnCurrent)
+ , cfa_parent(Scope, function(FnCurrent)), bind_scope(_, Context), scope(Scope).
+
+bind_scope_weak(Scope, Context) :- bind_scope(Scope, Context), bind_scope_demand(Scope, Context).
+bind_scope_weak(Scope, Context) :- cfa_parent(Scope, scope(ScopeParent)), bind_scope_weak(ScopeParent, Context), scope(Scope), scope(ScopeParent).
+bind_scope_weak(Scope, Context) :- bind_scope_weak(ScopeParent, Context),
+ cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
+
+% adhoc classes(unfinished):
+%bind_func(Fn, adhoc_class(Context)) := bind_func(Fn, adhoc(Context)), bind_scope(Scope, Context), cfa_parent(Scope, function(Fn)).
+
+%scope_parent(Scope, ScopeParent) :- cfa_parent(Scope, scope(ScopeParent)).
+%scope_parent(Scope, ScopeParent2) :- cfa_parent(Scope, scope(ScopeParent)), scope_parent(ScopeParent, ScopeParent2).
+
+%scope_function(Scope, Fn) :- cfa_parent(Scope, function(Fn)).
+%scope_function(Scope, Fn) :- cfa_parent(Scope, scope(ScopeParent)), scope_function(ScopeParent, Fn).
+
+
diff --git a/core/dependencies.lp b/core/dependencies.lp
new file mode 100644
index 0000000..5dab87b
--- /dev/null
+++ b/core/dependencies.lp
@@ -0,0 +1,9 @@
+node(a; b; c; d).
+depends(b,a).
+depends(c,a).
+depends(d, a).
+depends(d, c).
+
+level(X, 0) :- not depends(X, _); node(X).
+
+level(X, LEVEL):- LEVEL = #max{L+1, level(Y, L): level(Y, L), depends(X, Y)}; node(X); LEVEL > 0.
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 269bdff..9630011 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,149 +1,174 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
find_package(LLVM REQUIRED CONFIG)
+# MACRO (ADD_PCH_RULE _header_filename _src_list)
+# SET(_gch_filename "${_header_filename}.gch")
+# LIST(APPEND ${_src_list} ${_gch_filename})
+# SET (_args ${CMAKE_CXX_FLAGS})
+# LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename})
+# GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
+# foreach (_inc ${DIRINC})
+# LIST(APPEND _args "-I" ${_inc})
+# endforeach(_inc ${DIRINC})
+# SEPARATE_ARGUMENTS(_args)
+# add_custom_command(OUTPUT ${_gch_filename}
+# COMMAND rm -f ${_gch_filename}
+# COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
+# DEPENDS ${_header_filename})
+# ENDMACRO(ADD_PCH_RULE _header_filename _src_list)
+
+set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-tools")
+include(PCH_GCC4_v2)
+
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
link_directories(${LLVM_LIBRARY_DIRS})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
message ("MPATH:" ${CMAKE_MODULE_PATH})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
#find_package(Clang REQUIRED clangTooling libClang)
set(CMAKE_BUILD_TYPE Debug)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
set(POTASSCO_PATH "/opt/potassco/gringo" CACHE PATH "Path to gringo sources")
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
FILE (GLOB TEST_FILES ./tests/*.cpp)
message("TEST: " ${TEST_FILES})
set(SOURCE_FILES
${TEST_FILES}
./src/ast.cpp
./src/llvmlayer.cpp ./src/clasplayer.cpp
#./src/main.cpp
./src/utils.cpp
./src/passmanager.cpp
+
./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp ./src/pass/compilepass.cpp
./src/pass/cfgpass.cpp
- ./src/pass/logging.cpp
+ ./src/pass/loggerpass.cpp
+ ./src/pass/adhocpass.cpp
#./src/pass/rulespass.cpp
- ./src/instructions/instr-containers.cpp
+ ./src/compilation/instr-containers.cpp
+ ./src/compilation/latecontext.cpp
./src/query/containers.cpp
./src/query/ptrvalid.cpp
+ ./src/query/context.cpp
+
./src/attachments.cpp
+ ./src/contextrule.cpp
+ ./src/expressionserializer.cpp
+
#${POTASSCO_PATH}/app/shared/src/clingocontrol.cc
#${POTASSCO_PATH}/app/pyclingo/src/clingo_lib.cc
)
set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
set(COCO_SOURCE_FILES
${COCO_PATH}/Parser.h
${COCO_PATH}/Scanner.h
${COCO_PATH}/Parser.cpp
${COCO_PATH}/Scanner.cpp
)
-
-
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES(${COCO_PATH} ./src)
INCLUDE_DIRECTORIES(${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
)
include_directories(${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/)
#execute_process(COMMAND ${COCO_PATH}/gen-xreate WORKING_DIRECTORY OUTPUT_VARIABLE COCO_OUTPUT)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
-
-add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} src/ExternLayer.cpp src/ExternLayer.h)
+#add_definitions()
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Winvalid-pch -std=c++14 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0 -DWITH_THREADS=1")
-set(COCO_TARGET grammar)
+# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES)
+# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES)
+# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES)
+# ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES)
-add_custom_target(${COCO_TARGET}
- WORKING_DIRECTORY ${COCO_PATH}
-)
-
-add_custom_command(TARGET ${COCO_TARGET}
- PRE_BUILD
+add_custom_command(OUTPUT ${COCO_PATH}/Parser.cpp
COMMAND ${COCO_PATH}/gen-grammar
WORKING_DIRECTORY ${COCO_PATH}
+ DEPENDS ${COCO_PATH}/xreate.ATG
)
+add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} src/ExternLayer.cpp src/ExternLayer.h)
+
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
message(STATUS "BINARY DIR" ${CMAKE_BINARY_DIR})
#add_dependencies(${PROJECT_NAME} coverageTarget)
llvm_map_components_to_libnames(llvm_libs support core irreader all native nativecodegen)
message(STATUS "LLVM LIBS: " ${llvm_libs})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
)
message(STATUS "CLANG LIBS: " ${CLANG_LIBS})
message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS})
-add_definitions(-DWITH_THREADS=1)
+
FUNCTION(PREPEND var prefix)
SET(listVar "")
FOREACH(f ${ARGN})
LIST(APPEND listVar "${prefix}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
-
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
-
target_link_libraries(xreate ${GTEST_LIBRARIES} LLVM-${LLVM_VERSION} ${LIBCLASP_LIBS} ${CLANG_LIBS} pthread xml2 gcov tbb)
+#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
+#cotire(xreate)
\ No newline at end of file
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index ea80e4b..2bebce2 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,642 +1,726 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <clasplayer.h>
using namespace std;
namespace xreate{
class TypesResolver {
private:
const AST* ast;
std::map<std::string, TypeAnnotation> scope;
std::map<TypeAnnotation, int> signatures;
ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()){
return TypesResolver(ast, scope, signatures)(t, args);
}
std::vector<TypeAnnotation>
expandOperands(const std::vector<TypeAnnotation>& operands) {
std::vector<TypeAnnotation> pack;
pack.reserve(operands.size());
std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation& t){
return expandType(t);
});
return pack;
}
public:
TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
: ast(root), scope(scopeOuter), signatures(signaturesOuter) {
}
ExpandedType
operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>())
{
- assert(args.size() == t.bindings.size()); // invalid number of arguments
+ //assert(args.size() == t.bindings.size()); // invalid number of arguments
for (size_t i=0; i<args.size(); ++i)
{
scope[t.bindings.at(i)] = args.at(i);
}
switch (t.__operator)
{
case TypeOperator::ARRAY:
{
assert(t.__operands.size()==1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, 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::VARIANT: {
+ return ExpandedType(TypeAnnotation(t));
+ }
+
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());
+ bindings.reserve(bindings.size() + params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident){return ident.get(); });
}
+void
+TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields)
+{
+ fields.reserve(fields.size() + listFields.size());
+
+ std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
+ [](const Atom<Identifier_t>& ident){return ident.get(); });
+}
+
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);
+void Expression::setValueDouble(double value){
+ __valueD = value;
}
bool
Expression::isValid() const{
return (__state != INVALID);
}
Expression::Expression()
: __state(INVALID), op(Operator::NONE)
{}
AST::AST()
{
}
void
AST::addInterfaceData(const ASTInterface& interface, Expression&& data ) {
__interfacesData.emplace(interface, move(data));
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
void
AST::addExternData(ExternData &&data) {
__externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
}
void
AST::add(Function* f)
{
__functions.push_back(f);
- __indexFunctions[f->getName()] = __functions.size()-1;
+ __indexFunctions.emplace(f->getName(), FunctionSpecialization{"", __functions.size()-1});
+}
+
+void
+AST::add(Function* f, Atom <Identifier_t>&& context){
+ __functions.push_back(f);
+ __indexFunctions.emplace(f->getName(), FunctionSpecialization{context.get(), __functions.size()-1});
}
void
AST::add(MetaRuleAbstract *r)
{
__rules.push_back(r);
}
void
AST::add(TypeAnnotation&& t, Atom<Identifier_t>&& alias){
+ if (t.__operator == TypeOperator::VARIANT){
+ for (int i=0, size=t.fields.size(); i< size; ++i){
+ __dictVariants.emplace(t.fields[i], make_pair(t, i));
+ }
+ }
+
__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)) {
+ int count = __indexFunctions.count(name);
+ if (!count) {
return ManagedFnPtr::Invalid();
}
- return ManagedPtr<Function>(__indexFunctions.at(name), &__functions);
+
+ assert(count ==1);
+
+ auto range = __indexFunctions.equal_range(name);
+ return ManagedPtr<Function>(range.first->second.id, &this->__functions);
+}
+
+std::list<ManagedFnPtr>
+AST::getFunctionVariants(const std::string& name){
+ auto functions = __indexFunctions.equal_range(name);
+
+ std::list<ManagedFnPtr> result;
+ std::transform(functions.first, functions.second, inserter(result, result.end()),
+ [this](auto f){return ManagedFnPtr(f.second.id, &this->__functions);});
+
+ return result;
+}
+
+ManagedFnPtr
+AST::findFunctionVariant(const std::string& name, const FunctionSpecializationQuery& query) {
+ boost::optional<FunctionSpecialization> variant;
+ boost::optional<FunctionSpecialization> variantDefault;
+
+ auto functions = __indexFunctions.equal_range(name);
+
+ for (AST::FUNCTIONS_REGISTRY::const_iterator function = functions.first; function != functions.second; ++function){
+ const string& guard = function->second.guard;
+ if (guard.empty()){
+ assert(!variantDefault);
+ variantDefault = function->second;
+ }
+
+ if (query.context.count(guard)){
+ assert(!variant);
+ variant = function->second;
+ }
+ }
+
+ //Pickup default specialization if necessary
+ if (!variant){
+ variant = variantDefault;
+ }
+
+ if (variant) return ManagedPtr<Function>(variant->id, &__functions);
+
+ //case of no appropriate variant found
+ assert(0 == std::distance(functions.first, functions.second));
+
+ //case of external functions
+ return ManagedFnPtr::Invalid();
}
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));
}
+void
+AST::recognizeVariantIdentifier(Expression& identifier){
+ assert(identifier.__state == Expression::IDENT);
+
+ std::string name = identifier.getValueString();
+ if (__dictVariants.count(name)){
+ auto record = __dictVariants.at(name);
+ const TypeAnnotation& typ = record.first;
+
+ identifier.__state = Expression::VARIANT;
+ identifier.setValueDouble(record.second);
+ identifier.type = typ;
+ }
+}
+
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)
{
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];
}
+//TODO get rid of findSymbol. Determine symbol while AST parsing. Refind symbols not found while first pass.
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 && "Symbol not found");
}
-
-
bool
CodeScope:: hasDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
return (self->__declarations.count(symbol.identifier));
}
const Expression&
CodeScope::findDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
if (! self->__declarations.count(symbol.identifier))
{
// no declaration exists
assert(false);
}
return self->__declarations[symbol.identifier];
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ)
{
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e)
{
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards))
{}
MetaRuleAbstract::~MetaRuleAbstract(){}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition)
{}
RuleWarning::~RuleWarning(){}
void
RuleWarning::compile(ClaspLayer& layer)
{
layer.addRuleWarning(*this);
}
bool operator< (const Symbol& s1, const Symbol& s2)
{
return (s1.scope < s2.scope) || (s1.scope==s2.scope && s1.identifier<s2.identifier);
}
bool operator== (const Symbol& s1, const Symbol& s2)
{
return (s1.scope == s2.scope) && (s1.identifier==s2.identifier);
}
}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index c1ddc4b..e3ea188 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,519 +1,540 @@
#ifndef AST_H
#define AST_H
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "attachments.h"
#include "utils.h"
#include <algorithm>
namespace llvm{
class Value;
}
namespace xreate {
struct String_t{};
struct Identifier_t {};
struct Number_t {};
struct Type_t {};
template<typename A>
class Atom {};
//DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
template<> class Atom<Identifier_t>
{
public:
Atom(const std::wstring& value)
{
char buffer[32];
wcstombs(buffer, value.c_str(), 32);
__value = buffer;
}
Atom(std::string && name): __value(name) {}
const std::string& get() const{return __value; }
private:
std::string __value;
};
template<> class Atom<Number_t>
{
public:
Atom(wchar_t* value)
{
__value = wcstol(value, 0, 10);
}
Atom(int value)
: __value(value)
{}
double get()const {return __value; }
private:
double __value;
};
template<> class Atom<String_t>
{
public:
- Atom(const std::wstring& value)
- : __value(++value.begin(), --value.end())
- {}
+ Atom(const std::wstring& value){
+ assert(value.size());
+ __value = std::string(++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};
+enum class TypeOperator{NONE, CALL, CUSTOM, VARIANT, ARRAY, TUPLE, STRUCT, ACCESS, LINK};
struct llvm_array_tag {}; struct struct_tag{};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
class TypeAnnotation
{
public:
TypeAnnotation();
TypeAnnotation (const Atom<Type_t>& typ);
TypeAnnotation (TypePrimitive typ);
TypeAnnotation (llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation (TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation (TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
+ void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator< (const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId=-1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator
{
-ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, INDEX, IF, SWITCH, CASE, LOGIC_AND
+ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, LOOP_CONTEXT, INDEX, IF, SWITCH, SWITCH_ADHOC, CASE, CASE_DEFAULT, LOGIC_AND, ADHOC, CONTEXT_RULE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
template<class Target>
struct ManagedPtr
{
static ManagedPtr<Target> Invalid(){
return ManagedPtr<Target>();
}
ManagedPtr(): __storage(0) {}
ManagedPtr(unsigned int id, const std::vector<Target*>* storage)
: __id(id), __storage(storage)
{}
Target&
operator*() const
{
assert(isValid() && "Invalid Ptr");
return *__storage->at(__id);
}
void operator=(const ManagedPtr<Target>& other)
{
__id = other.__id;
__storage = other.__storage;
}
bool
operator == (const ManagedPtr<Target>& other)
{
return isValid() && (__id == other.__id);
}
Target*
operator->() const noexcept
{
assert(isValid() && "Invalid Ptr");
return __storage->at(__id);
}
inline bool isValid() const
{
return (__storage) && (0 <= __id) && (__id < __storage->size());
}
inline operator bool() const {
return isValid();
}
ManagedPtr<Target>& operator++()
{
++__id;
return *this;
}
- inline unsigned int id()
+ inline unsigned int id() const
{
return __id;
}
private:
unsigned int __id =0;
const std::vector<Target*> * __storage=0;
};
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
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;
+ void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
- bool isNone() const;
bool isValid() const;
- enum {INVALID, COMPOUND, IDENT, NUMBER, STRING, NONE} __state = INVALID;
+ enum {INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT} __state = INVALID;
Operator op;
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
TypeAnnotation type;
std::map<std::string, Expression> tags;
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
};
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom){
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier
{NONE, ASSERT, REQUIRE};
enum class DomainAnnotation
{FUNCTION, VARIABLE};
class RuleArguments: public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards: public std::vector<Expression>
{
public:
void add(Expression&& e);
};
class ClaspLayer;
class LLVMLayer;
class MetaRuleAbstract
{
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(ClaspLayer& layer) =0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning: public MetaRuleAbstract
{
friend class ClaspLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(ClaspLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VID;
/*
class Expression: ExpressionAbstract
{
friend class CFGPass;
public:
llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
};
*/
typedef std::pair<VID, TypeAnnotation> VariableDefinition;
typedef std::pair<VID, Expression> VariableDeclaration;
typedef std::pair<Expression, TagModifier> Tag;
struct Symbol
{
VID identifier;
CodeScope * scope;
};
struct SymbolTags_t{};
template<>
struct AttachmentsDict<SymbolTags_t> {
typedef std::map<std::string, Expression> Data;
static const unsigned int key = 2;
};
bool operator< (const Symbol& s1, const Symbol& s2);
bool operator== (const Symbol& s1, const Symbol& s2);
class CodeScope
{
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent=0);
void setBody(const Expression& body);
void addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body);
void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
//TODO exclude forceCompile partz
Symbol findSymbol(const std::string &name);
static const Expression& findDeclaration(const Symbol& symbol);
static TypeAnnotation& findDefinition(const Symbol& symbol);
static bool hasDeclaration(const Symbol& symbol);
~CodeScope();
std::vector<std::string> __args;
Expression __body; //TODO move __body to __declarations[0]
SymbolAttachments attachments;
std::map<std::string, VID> __vartable;
/**
* definition of return type has variable index Zero(0)
*/
//TODO move __definitions to SymbolsAttachments data
std::unordered_map<VariableDefinition::first_type, VariableDefinition::second_type> __definitions;
std::unordered_map<VariableDeclaration::first_type, VariableDeclaration::second_type> __declarations;
+ std::vector<Expression> tags;
+ std::vector<Expression> contextRules;
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;
+ bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
+
+ Expression guardContext;
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
+ CFA, DFA, Extern, Adhoc
+};
+
+struct FunctionSpecialization {
+ std::string guard;
+ size_t id;
+};
+
+struct FunctionSpecializationQuery {
+ std::unordered_set<std::string> context;
};
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(Function* f, Atom <Identifier_t>&& context);
+
void add(MetaRuleAbstract* r);
ManagedScpPtr add(CodeScope* scope);
std::string getModuleName();
ManagedPtr<Function> findFunction(const std::string& name);
+ typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
+ std::list<ManagedPtr<Function>> getAllFunctions();
+
template<class Target>
ManagedPtr<Target> begin();
std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
- std::map<std::string, unsigned int> __indexFunctions;
+ FUNCTIONS_REGISTRY __indexFunctions;
// ***** TYPES SECTION *****
public:
std::map<std::string, TypeAnnotation> __indexTypeAliases;
ExpandedType expandType(const TypeAnnotation &t) const;
ExpandedType findType(const std::string& name);
void add(TypeAnnotation&& t, Atom<Identifier_t>&& alias);
+void recognizeVariantIdentifier(Expression& identifier);
+
private:
+std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
// ***** 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 c074c43..adc4701 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,623 +1,670 @@
#include "clasplayer.h"
#include <iostream>
#include "utils.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <gringo/scripts.hh>
using namespace std;
namespace xreate {
void
ClaspLayer::printWarnings(std::ostream& out)
{
const std::string warningTag = "warning";
auto warningsRange = __model.equal_range(warningTag);
for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) {
unsigned int warningId;
Gringo::Value params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Value>(warning->second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
ClaspLayer::onModel(Gringo::Model const &model) {
std::list<std::string> warnings;
cout << "Model: " << endl;
const string& atomBindVar = Config::get("clasp.bindings.variable");
const string& atomBindFunc = Config::get("clasp.bindings.function");
+ const string& atomBindScope = Config::get("clasp.bindings.scope");
for (Gringo::Value atom : model.atoms(Gringo::Model::ATOMS)) {
atom.print(cout);
cout <<" | "<< endl;
- if (*atom.name() == atomBindVar || *atom.name() == atomBindFunc){
+ if (*atom.name() == atomBindVar || *atom.name() == atomBindFunc || *atom.name() == atomBindScope){
string name = *std::get<1>(parse<Gringo::Value, Gringo::Value>(atom)).name();
__model.emplace(move(name), move(atom));
- continue;
}
__model.emplace(*atom.name(), move(atom));
}
return true;
}
list<string>
multiplyLists(list<list<string>> &&lists) {
typedef list<string> StringList;
assert(lists.size());
StringList result(*lists.begin());
lists.pop_front();
boost::format concat("%s, %s");
for (StringList &list: lists) {
StringList::const_iterator end = result.end();
for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
if (list.size() == 0) continue;
StringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
result.push_back(str(concat %(*expr1I) %(*expr2I)));
*expr1I = str(concat %(*expr1I) %(*expr2I));
}
}
return result;
}
void
ClaspLayer::setCFAData(CFAGraph &&graph) {
cfagraph = graph;
}
void
ClaspLayer::addDFAData(DFAGraph &&graph)
{
dfaData = graph;
std::set<SymbolPacked> symbols;
ostream &cout = __partGeneral;
cout << endl << "%\t\tStatic analysis: DFA" << endl;
std::vector<std::pair<SymbolPacked, SymbolPacked>>::iterator i1;
std::vector<DFGConnection>::iterator i2;
boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
boost::format format2Args("(%1%, %2%)");
for (i1= dfaData.__edges.begin(), i2 = dfaData.__data.begin(); i1!= dfaData.__edges.end(); ++i1, ++i2 )
{
string edgeName;
switch (*i2)
{
case DFGConnection::OPT: edgeName = "opt"; break;
case DFGConnection::ALIAS: edgeName = "alias"; break;
case DFGConnection::PROTO: edgeName = "proto"; break;
}
cout << formatDfaConnection
%(format2Args %(i1->first.identifier) %(i1->first.scope)).str()
%(format2Args %(i1->second.identifier) %(i1->second.scope)).str()
%edgeName
<< " %" <<getHintForPackedSymbol(i1->first) << " - " << getHintForPackedSymbol(i1->second)
<<endl;
symbols.insert(i1->first);
symbols.insert(i1->second);
}
boost::format formatBind("bind(%1%, %2%).");
for (const pair<SymbolPacked, Expression>& tag: dfaData.__tags)
{
for (string variant: compile(tag.second)) {
cout << (formatBind
% (format2Args %(tag.first.identifier) %(tag.first.scope))
% (variant))
<< "%" << getHintForPackedSymbol(tag.first)
<< endl;
}
symbols.insert(tag.first);
}
for (const SymbolPacked& s: symbols)
{
cout << "v(" << format2Args % (s.identifier) % (s.scope) << ")."
<< " %" << getHintForPackedSymbol(s)
<<endl;
}
}
void
ClaspLayer::involveCFAData() {
ostream &cout = __partTags;
const std::string& atomBinding = Config::get("clasp.bindings.function");
const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
//show function tags
int counterTags = 0;
boost::format formatFunction("function(%1%).");
- boost::format formatBind("%1%(%2%, %3%).");
+ boost::format formatBind(atomBinding + "(%1%, %2%).");
for (auto function: cfagraph.__nodesFunction.left) {
cout << formatFunction % (function.second) << std::endl;
for (const auto& tag_: boost::make_iterator_range(cfagraph.__functionTags.equal_range(function.first))){
const Tag& tag = tag_.second;
list<string> tagRaw = compile(tag.first);
assert(tagRaw.size() == 1);
cout << formatBind
- % (atomBinding)
% (function.second)
% (tagRaw.front())
<< endl;
++counterTags;
}
}
if (counterTags == 0) {
cout << "%no tags at all" << endl;
}
- //show scope tags:
+ //declare scopes
boost::format formatScope("scope(%1%).");
for (auto scope: __indexScopes) {
//std::string function = scope.first.
cout << formatScope % scope.second << std::endl;
}
+ //show context rules:
+ for (auto rule: cfagraph.__contextRules) {
+ cout << ContextRule(rule.second).compile(rule.first) << std::endl;
+ };
+
+ //show scope tags:
counterTags = 0;
- boost::format formatScopeBind("%1%(%2%, %3%).");
+ boost::format formatScopeBind(atomBindingScope + "(%1%, %2%).");
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;
+ cout << formatScopeBind % scopeId %(tagRaw.front()) << endl;
++counterTags;
}
if (counterTags == 0) {
- cout << "%no tags at all" << endl;
+ cout << "%scope tags: no tags at all" << endl;
}
cout << endl << "%\t\tStatic analysis: CFA" << endl;
- boost::format formatCall("call(%1%, %2%).");
- for (const auto &relation: cfagraph.__relations) {
+ //parent connections
+ //TEST CFG parent function
+ boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
+ for (const auto &relation: cfagraph.__parentFunctionRelations) {
+ const string& function = cfagraph.__nodesFunction.left.at(relation.second);
+
+ cout << formatFunctionParent % relation.first % function << endl;
+ }
+
+ //TEST CFG parent scope
+ boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
+ for (const auto &relation: cfagraph.__parentScopeRelations) {
+ cout << formatScopeParent % relation.first % relation.second << endl;
+ }
+
+ //call connections
+ boost::format formatCall("cfa_call(%1%, %2%).");
+
+ for (const auto &relation: cfagraph.__callRelations) {
const ScopePacked scopeFrom = relation.first;
const string& functionTo = cfagraph.__nodesFunction.left.at(relation.second);
cout << formatCall % (scopeFrom) % (functionTo) << endl;
}
}
void
ClaspLayer::addRuleWarning(const RuleWarning &rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch (argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list<string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return compile(guard);
});
const list<string>& guards = multiplyLists(std::move(guardsRaw));
list<string> &&branches = compileNeg(rule.__condition);
boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
for (const string &guardsJoined: guards)
for (const string &branch: branches) {
unsigned int hook = registerWarning(string(rule.__message));
__partGeneral << formatWarning
%(hook)
%(boost::algorithm::join(vars, ", "))
%(branch)
%(guardsJoined)
%(boost::algorithm::join(domains, ", "))
<<endl;
}
}
std::list<std::string>
- ClaspLayer::compile(const Expression &e) const {
+ ClaspLayer::compile(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
std::list<list<string>> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
- [this](const Expression &e) {
- return compile(e);
+ [](const Expression &e) {
+ return ClaspLayer::compile(e);
});
list<string> &&operands_ = multiplyLists(std::move(operands));
result.push_back(boost::str(boost::format("%1%(%2%)") % (e.__valueS) % (boost::algorithm::join(operands_, ", "))));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::NONE: {
switch (e.__state) {
case Expression::IDENT:
result.push_back(e.__valueS);
break;
case Expression::NUMBER:
result.push_back(to_string(e.__valueD));
break;
default:
assert(true);
}
break;
}
default: break;
}
- if (e.isNone()){
- result.push_back(e.__valueS);
- }
+//TODO Null ad hoc ClaspLayer implementation
+// if (e.isNone()){
+// result.push_back(e.__valueS);
+// }
assert(result.size());
return result;
}
std::list<std::string>
- ClaspLayer::compileNeg(const Expression &e) const {
+ ClaspLayer::compileNeg(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
list<string> operands1 = compile(e.operands.at(0));
list<string> operands2 = compile(e.operands.at(1));
boost::format formatNeg("%1%, not %2%");
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back(rawOp.front());
break;
};
default:
assert(true);
}
return result;
}
unsigned int
ClaspLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
ClaspLayer::involveImports() {
ostream &out = __partGeneral;
for (string fn: ast->__rawImports)
{
std::ifstream file(fn);
if (!file) continue;
while(!file.eof()){
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
ClaspLayer::addRawScript(std::string&& script){
__partGeneral << script;
}
void
ClaspLayer::run() {
involveImports();
involveCFAData();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data());
ctl.add("base", {}, program.str());
ctl.ground({{"base", {}}}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
this->onModel(model);
return true;
}, {});
if (result == Gringo::SolveResult::SAT) {
cout << FGRN("SUCCESSFULLY") << endl;
} else {
cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process clasp data
- for (IQuery* q: __queries)
+ for (auto q: __queries)
{
- q->init(this);
+ q.second->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
ClaspLayer::ModelFragment
ClaspLayer::query(const std::string& atom)
{
if (! __model.count(atom)){
return boost::none;
}
return ModelFragment(__model.equal_range(atom));
}
ScopePacked
ClaspLayer::pack(CodeScope* scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
SymbolPacked
ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
SymbolPacked result;
result.scope = pack(symbol.scope);
result.identifier = symbol.identifier;
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
ClaspLayer::unpack(const SymbolPacked& symbol)
{
return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
};
std::string
ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){
auto result = __indexSymbolNameHints.find(symbol);
return (result == __indexSymbolNameHints.end())? "" : result->second;
}
/*
void AspOutPrinter::reportSolution(const Clasp::Solver&, const Clasp::Enumerator&, bool complete) {
if (complete) std::cout << "No more models!" << std::endl;
else std::cout << "More models possible!" << std::endl;
}
void AspOutPrinter::reportModel(const Clasp::Solver& s, const Clasp::Enumerator&) {
std::cout << "Model " << s.stats.solve.models << ": \n";
// get the symbol table from the solver
const Clasp::AtomIndex& symTab = *s.strategies().symTab;
for (Clasp::AtomIndex::const_iterator it = symTab.begin(); it != symTab.end(); ++it)
{
// print each named atom that is true w.r.t the current assignment
}
std::cout << std::endl;
}
*/
/*****************************************
* CFAGraph
*****************************************
*/
void
- CFAGraph::addFunctionNodeTags(const std::string& function, const std::vector<Tag>&tags) {
+ CFAGraph::addFunctionAnnotations(const std::string& function, const std::vector<Tag>&tags) {
unsigned int fid = registerNodeFunction(function);
for (Tag tag: tags){
__functionTags.emplace(fid, tag);
}
}
void
- CFAGraph::addScopeNodeTags(const ScopePacked& scope, const std::vector<Expression>& tags){
+ CFAGraph::addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>& tags){
for (Expression tag: tags){
__scopeTags.emplace(scope, tag);
}
}
void
- CFAGraph::addLink(const ScopePacked& scopeFrom, const std::string& functionTo) {
+ CFAGraph::addContextRules(const ScopePacked& scope, const std::vector<Expression>& rules){
+ for (Expression rule: rules){
+ __contextRules.emplace(scope, rule);
+ }
+ }
+
+ void
+ CFAGraph::addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo) {
unsigned int idFuncTo = registerNodeFunction(functionTo);
- __relations.emplace(scopeFrom, idFuncTo);
+ __callRelations.emplace(scopeFrom, idFuncTo);
+ }
+
+ void
+ CFAGraph::addParentConnection(const ScopePacked& scope, const std::string& functionParent){
+ __parentFunctionRelations.emplace(scope, registerNodeFunction(functionParent));
+ }
+
+ void
+ CFAGraph::addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent){
+ __parentScopeRelations.emplace(scope, scopeParent);
}
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))
+ if (!__graph->isConnected(__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& symbolFrom){
if (__link != DFGConnection::ALIAS){
assert(false && "Undefined behaviour");
}
for (const Expression& tag: symbolFrom.tags){
__graph->__tags.emplace(__nodeTo, tag);
}
}
void operator()(const SymbolInvalid&){
if (__link == DFGConnection::ALIAS) return;
if (__link == DFGConnection::OPT) return;
assert(false && "Undefined behaviour");
}
VisitorAddLink(DFAGraph* const dfagraph, const SymbolPacked& nodeTo, DFGConnection link):
__graph(dfagraph), __nodeTo(nodeTo), __link(link) {}
private:
DFAGraph* const __graph;
SymbolPacked __nodeTo;
DFGConnection __link;
};
bool
- DFAGraph::linkExists(const SymbolPacked& node1, const SymbolPacked& node2)
+ DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom)
{
- auto range = __outEdges.equal_range(node2);
+ auto range = __outEdges.equal_range(identifierFrom);
for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
{
- if (__edges[edge->second].second == node1)
+ if (__edges[edge->second].second == identifierTo)
return true;
}
return false;
}
void
- DFAGraph::addLink(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
+ DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
VisitorAddLink visitor(this, nodeTo, link);
boost::apply_visitor(visitor, nodeFrom);
}
void
- DFAGraph::addTag(SymbolNode& node, Expression&& tag) {
+ DFAGraph::addAnnotation(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);
+ IQuery*
+ ClaspLayer::registerQuery(IQuery *query, const QueryId& id) {
+ return __queries.emplace(id, query).first->second;
+ }
+
+ IQuery*
+ ClaspLayer::getQuery(const QueryId& id){
+ assert(__queries.count(id) && "Undefined query");
+ return __queries.at(id);
}
}
diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h
index c89196a..2e208d3 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,202 +1,239 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_H
-#include <ast.h>
+#include "ast.h"
+#include "contextrule.h"
#include <clingo/clingocontrol.hh>
#include <string>
#include <climits>
#include <boost/bimap.hpp>
#include <boost/optional.hpp>
#include <list>
namespace xreate {
typedef unsigned int ScopePacked;
class CFAGraph {
friend class ClaspLayer;
public:
- void addFunctionNodeTags(const std::string& function, const std::vector<Tag>&tags);
- void addScopeNodeTags(const ScopePacked& scope, const std::vector<Expression>&tags);
- void addLink(const ScopePacked& scopeFrom, const std::string& functionTo);
- //void print(std::ostream &cout) const;
+ void addFunctionAnnotations(const std::string& function, const std::vector<Tag>&tags);
+ void addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>&tags);
+ void addContextRules(const ScopePacked& scope, const std::vector<Expression>&rules);
+
+ void addCallConnection(const ScopePacked& scopeFrom, const std::string& functionTo);
+ void addParentConnection(const ScopePacked& scope, const std::string& functionParent);
+ void addParentConnection(const ScopePacked& scope, const ScopePacked& scopeParent);
+// void addScopeRetIdentifier(const ScopePacked& scope, const SymbolPacked& identifier);
private:
- std::map<ScopePacked, unsigned int> __relations;
+ std::map<ScopePacked, unsigned int> __parentFunctionRelations;
+ std::map<ScopePacked, ScopePacked> __parentScopeRelations;
+ std::multimap<ScopePacked, unsigned int> __callRelations;
boost::bimap<unsigned int, std::string > __nodesFunction;
std::multimap<unsigned int, Tag> __functionTags;
std::multimap<ScopePacked, Expression> __scopeTags;
+ std::multimap<ScopePacked, ContextRule> __contextRules;
unsigned int registerNodeFunction(const std::string& fname);
};
struct SymbolPacked
{
VID identifier;
ScopePacked scope;
};
struct SymbolTransient{
std::list<Expression> tags;
};
struct SymbolInvalid{};
typedef boost::variant<SymbolPacked, SymbolTransient, SymbolInvalid> SymbolNode;
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
enum class DFGConnection{
ALIAS, OPT, PROTO};
class VisitorAddTag;
class VisitorAddLink;
class DFAGraph
{
friend class ClaspLayer;
friend class VisitorAddTag;
friend class VisitorAddLink;
public:
- void addTag(SymbolNode& node, Expression&& tag);
- void addLink(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link);
- bool linkExists(const SymbolPacked& node1, const SymbolPacked& node2);
+ void addAnnotation(SymbolNode& identifier, Expression&& tag);
+ void addConnection(const SymbolPacked& identifierTo, const SymbolNode& identifierFrom, DFGConnection link);
+ bool isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom);
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() {}
};
+ enum class QueryId{
+ ContainersQuery,
+ ContextQuery,
+ PtrvalidQuery
+ };
+
class ClaspLayer {
+ friend class ContextRule;
public:
AST *ast;
DFAGraph dfaData;
CFAGraph cfagraph;
ClaspLayer();
- void registerdQuery(IQuery* query);
+ IQuery* registerQuery(IQuery* query, const QueryId& id);
+ IQuery* getQuery(const QueryId& id);
void addFunctionTags(const std::string &function, const std::vector<Tag> &tags);
void setCFAData(CFAGraph &&graph);
void addDFAData(DFAGraph &&graph);
void addRuleWarning(const RuleWarning &rule);
void run();
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Value& atom);
typedef std::multimap<std::string, Gringo::Value>::const_iterator ModelIterator;
typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelFragment;
ModelFragment query(const std::string& atom);
ScopePacked pack(CodeScope* scope);
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
Symbol unpack(const SymbolPacked& symbol);
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
void addRawScript(std::string&& script);
+
private:
// all query plugins to process clasp data
- std::list<IQuery*> __queries;
+ std::map<QueryId, IQuery*> __queries;
std::multimap<std::string, Gringo::Value> __model;
std::map<unsigned int, std::string> __warnings;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<CodeScope*> __registryScopes;
void printWarnings(std::ostream& out);
bool onModel(Gringo::Model const &model);
- std::list<std::string> compile(const Expression &e) const;
- std::list<std::string> compileNeg(const Expression &e) const;
+ static std::list<std::string> compile(const Expression &e);
+ static std::list<std::string> compileNeg(const Expression &e);
unsigned int registerWarning(std::string &&message);
void involveImports();
void involveCFAData();
-
-
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Value& atom)
{
return atom.num();
}
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Value& atom)
{
return *atom.string();
}};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Value& atom)
{
auto result = ClaspLayer::parse<unsigned int, unsigned int>(atom);
return SymbolPacked{std::get<0>(result), std::get<1>(result)};
}};
template<>
struct ParseImplAtom<Gringo::Value> {
static Gringo::Value get(const Gringo::Value& atom)
{
return atom;
}};
+ template<>
+ struct ParseImplAtom<Expression> {
+ static Expression get(const Gringo::Value& atom)
+ {
+ switch (atom.type()){
+ case Gringo::Value::NUM: return Expression(atom.num());
+ case Gringo::Value::ID: return Expression((std::string(atom.string())));
+ case Gringo::Value::FUNC: {
+ Expression result(Operator::CALL, {Expression(std::string(atom.name()))});
+ for(const Gringo::Value& arg: atom.args()){
+ result.addArg(ParseImplAtom<Expression>::get(arg));
+ }
+
+ return result;
+ }
+
+ default: {
+ assert(false);
+ }
+ }
+ }};
+
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/compilation/instr-containers.cpp
similarity index 83%
rename from cpp/src/instructions/instr-containers.cpp
rename to cpp/src/compilation/instr-containers.cpp
index 793aec7..38192a0 100644
--- a/cpp/src/instructions/instr-containers.cpp
+++ b/cpp/src/compilation/instr-containers.cpp
@@ -1,501 +1,575 @@
#include "instr-containers.h"
#include "llvmlayer.h"
#include "ast.h"
+#include "query/context.h"
#include "query/containers.h"
#include "query/ptrvalid.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
CompilePass::CodeScopeUnit* scope = context.scope; \
- CompilePass::FunctionUnit* function = context.function; \
+ CompilePass::FunctionUnit* function = context.function;
Instructions::Instructions(CompilePass::Context ctx)
: context(ctx), tyNum (static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num)))))
{}
llvm::Value*
Instructions::compileMapSolid(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT
//initialization
std::string varIn = expr.getOperands()[0].getValueString();
Symbol symbolIn = scope->scope->findSymbol(varIn);
ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
size_t size = implIn.size;
CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__args[0];
Iterator* it = Iterator::create(context, symbolIn);
llvm::Value *rangeFrom = it->begin();
llvm::Value *rangeTo = it->end();
//definitions
ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
llvm::IRBuilder<> &builder = llvm->builder;
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postloop", function->raw);
Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
// * initial check
Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
// create PHI:
builder.SetInsertPoint(blockLoop);
llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// loop body:
Value* elIn = it->get(stateLoop, varEl);
CompilePass::CodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
scopeLoopUnit->bindArg(elIn, move(varEl));
Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop,llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, blockLoop);
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
Instructions::compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string hintRetVar)
{
EXPAND_CONTEXT
UNUSED(function);
//TODO find out symbol identifier in order to name it in raw llvm;
llvm::Value* data = scope->compileSymbol(dataSymbol);
const Expression& decl = CodeScope::findDeclaration(dataSymbol);
if (decl.op == Operator::LIST) {
assert(indexes.size() == 1);
return llvm->builder.CreateExtractElement(data, indexes[0], NAME("el"));
}
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
Value *pEl = llvm->builder.CreateGEP(data, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
Instructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx){
EXPAND_CONTEXT
UNUSED(scope);
TypeUtils types(llvm);
std::vector<std::string>&& fields = types.getStructFields(t);
for (unsigned i=0, size = fields.size(); i<size; ++i){
if (fields.at(i) == idx){
std::vector<llvm::Value*> refs;
llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::ConstantInt* zero = llvm::ConstantInt::get(tyInt, 0, false);
llvm::BasicBlock *blockSafe = llvm::BasicBlock::Create(llvm::getGlobalContext(), "safe", function->raw);
// safety check: not null ptr
Symbol s;
if (! QueryPtrValid::assertValidPtr(s)){
PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
llvm->initExceptionBlock(blockException);
}
llvm->builder.SetInsertPoint(blockSafe);
std::vector<Value*> indexes;
//dereference pointer
if (types.isPointer(t)){
indexes.push_back(zero);
}
indexes.push_back(ConstantInt::get(tyInt, i));
Value* addr = llvm->builder.CreateGEP(aggregate, indexes);
return llvm->builder.CreateLoad(addr);
}
}
assert(false && "not found required struct field");
}
llvm::Value*
Instructions::compileFold(const Expression& fold, const std::string& hintRetVar)
{
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = scope->scope->findSymbol(fold.getOperands()[0].getValueString());
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
llvm::Value* rangeFrom = it->begin();
llvm::Value* rangeTo = it->end();
llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
llvm::Value* valSat = nullptr;
bool flagHasSaturation = false; //false; // TODO add `saturation` ann.
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
llvm::BasicBlock *blockEarly = llvm::BasicBlock::Create(llvm::getGlobalContext(), "earlyret", function->raw);
// * initial check
Value* condBefore = llvm->builder.CreateICmpNE(rangeFrom, rangeTo);
llvm->builder.CreateCondBr(condBefore, blockLoop, blockEarly);
llvm->builder.SetInsertPoint(blockEarly);
llvm->builder.CreateRet(accumInit);
//TODO implement saturation; add unittests;
// Saturation check
if (flagHasSaturation)
{
Value* condSat = llvm->builder.CreateICmpNE(accumInit, valSat);
llvm->builder.CreateCondBr(condSat, blockLoop, blockAfterLoop);
}
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(tyNum, 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *stateLoop = llvm->builder.CreatePHI(rangeFrom->getType(), 2, "foldIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// * loop body
CodeScope* scopeLoop = fold.blocks.front();
CompilePass::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(stateLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * break checks, continue checks
if (flagHasSaturation)
{
llvm::BasicBlock *blockChecks = llvm::BasicBlock::Create(llvm::getGlobalContext(), "checks", function->raw);
Value* condSat = llvm->builder.CreateICmpNE(accumNext, valSat);
llvm->builder.CreateCondBr(condSat, blockChecks, blockAfterLoop);
llvm->builder.SetInsertPoint(blockChecks);
}
// * computing next iteration state
Value *stateLoopNext = it->move(stateLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
stateLoop->addIncoming(stateLoopNext, llvm->builder.GetInsertBlock());
// * next iteration checks
Value* condAfter = llvm->builder.CreateICmpNE(stateLoopNext, rangeTo);
llvm->builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
+llvm::Value*
+Instructions::compileLoopContext(const Expression& expression, const std::string& hintRetVar){
+ EXPAND_CONTEXT
+ llvm::IRBuilder<>& builder = llvm->builder;
+
+ ContextQuery* queryContext = reinterpret_cast<ContextQuery*> (context.pass->man->clasp->getQuery(QueryId::ContextQuery));
+
+ ScopePacked scopeOuterId = context.pass->man->clasp->pack(scope->scope);
+ std::list<Expression> contextScopeOuter = queryContext->getContext(scopeOuterId);
+ std::string classSelected = expression.operands[0].getValueString();
+
+ std::list<Expression> elementsSelected;
+ for (const Expression& c: contextScopeOuter){
+ if (c.op == Operator::CALL && c.getValueString() == classSelected){
+ assert(c.operands.size());
+ elementsSelected.push_back(c.operands[0]);
+ }
+ }
+
+ assert(expression.blocks.size());
+ CodeScope* scopeInner = expression.blocks.front();
+ CompilePass::CodeScopeUnit* scopeInnerUnit = function->getScopeUnit(scopeInner);
+ ScopePacked scopeInnerId = context.pass->man->clasp->pack(scopeInner);
+
+ llvm::Value* result = nullptr;
+ for (const Expression& element: elementsSelected){
+ std::string blockName = "context" + element.getValueString();
+ llvm::BasicBlock *blockInner = llvm::BasicBlock::Create(llvm::getGlobalContext(), blockName, function->raw);
+ builder.CreateBr(blockInner);
+ builder.SetInsertPoint(blockInner);
+
+ queryContext->forceContext(scopeInnerId, {element});
+ scopeInnerUnit->reset();
+ result = scopeInnerUnit->compile();
+ }
+
+ return result;
+}
+
llvm::Value*
Instructions::compileIf(const Expression& exprIf, const std::string& hintRetVar)
{
EXPAND_CONTEXT
//initialization:
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
llvm::BasicBlock *blockAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", function->raw);
llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", function->raw);
llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
llvm::PHINode *ret = builder.CreatePHI(tyNum, 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
//TODO implement switch
llvm::Value*
Instructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar){
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
- UNUSED(llvm);
- return nullptr;
- //llvm::IRBuilder<>& builder = llvm->builder;
- //builder.CreateSwitch()
+ assert(exprSwitch.operands.size() >= 2);
+ assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT);
+ int countCases = exprSwitch.operands.size()-1;
+ llvm::IRBuilder<>& builder = llvm->builder;
+
+ llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchAfter", function->raw);
+ builder.SetInsertPoint(blockEpilog);
+ llvm::Type* exprSwitchType = llvm->toLLVMType(ExpandedType(exprSwitch.type));
+ llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
+
+ builder.SetInsertPoint(blockProlog);
+ llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
+ llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", function->raw);
+ llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(conditionSwitch, blockDefault, countCases);
+
+ for (int size = exprSwitch.operands.size(), i=2; i<size; ++i){
+ llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case" + std::to_string(i), function->raw);
+
+ llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
+ builder.SetInsertPoint(blockCase);
+ llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
+ builder.CreateBr(blockEpilog);
+
+ ret->addIncoming(resultCase, builder.GetInsertBlock());
+ builder.SetInsertPoint(blockProlog);
+ instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(condCase), blockCase);
+ }
+
+ //compile default block:
+ builder.SetInsertPoint(blockDefault);
+ CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
+ llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
+ builder.CreateBr(blockEpilog);
+ ret->addIncoming(resultDefault, builder.GetInsertBlock());
+ builder.SetInsertPoint(blockEpilog);
+
+ return ret;
}
llvm::Value*
Instructions::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
const size_t& __size = expr.getOperands().size();
const Expression& __data = expr;
ArrayType* typList = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I32, __size))));
Type*typI32 = llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::I32)));
std::vector<Constant *> list;
list.reserve(__size);
const std::vector<Expression> operands = __data.getOperands();
std::transform(operands.begin(), operands.end(), std::inserter(list, list.begin()),
[typI32](const Expression& e){return ConstantInt::get(typI32, e.getValueDouble());});
Value* listSource = ConstantArray::get(typList, ArrayRef<Constant*>(list));
/*
Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
*/
return listSource;
}
llvm::Value*
Instructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar)
{
EXPAND_CONTEXT
UNUSED(function);
UNUSED(scope);
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; //TODO is used somewhere?
const Expression& sourceDecl;
CompilePass::Context context;
llvm::Type* sourceRawType =nullptr;
public:
IteratorForward(CompilePass::Context ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
: llvm(ctx.pass->man->llvm), current(s), source(implementation.source), linkedlist(source), sourceScope(source.scope), sourceUnit(new CompilePass::CodeScopeUnit(source.scope, ctx.function, ctx.pass)),
sourceDecl(CodeScope::findDeclaration(source)),
context(ctx)
{
}
llvm::Value* begin() {
switch(sourceDecl.op) {
case xreate::Operator::LIST:
{
sourceRawType = Type::getInt32Ty(llvm::getGlobalContext());
return ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 0);
};
case xreate::Operator::LIST_RANGE:{
assert(sourceDecl.operands.size()==2);
llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
sourceRawType = result->getType();
return result;
};
default: break;
}
if (linkedlist){
llvm::Value* result = sourceUnit->process(sourceDecl);
sourceRawType = result->getType();
return result;
}
assert(false);
}
llvm::Value* end(){
switch(sourceDecl.op) {
case xreate::Operator::LIST: {
size_t idLast = sourceDecl.operands.size() - 1;
return ConstantInt::get(sourceRawType, idLast);
}
case xreate::Operator::LIST_RANGE: {
assert(sourceDecl.operands.size() == 2);
return sourceUnit->process(sourceDecl.operands.at(1));
};
default: break;
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value* get(Value* index,const std::string& hintRetVar="") override{
const Expression& currentDecl = CodeScope::findDeclaration(current);
switch (currentDecl.op) {
case xreate::Operator::LIST: {
//TODO re check is it right scope(source) to compilation currentDecl. Write unittests for this.
//llvm::Value* currentValue = sourceUnit->process(currentDecl);
return Instructions(context).compileArrayIndex(current, vector<Value *>{index});
};
case xreate::Operator::LIST_RANGE: {
return index;
};
case xreate::Operator::MAP: {
assert(currentDecl.getOperands().size()==1);
assert(currentDecl.bindings.size());
assert(currentDecl.blocks.size());
CodeScope* scopeLoop = currentDecl.blocks.front();
const std::string& varIn = currentDecl.getOperands()[0].getValueString();
std::string varEl = currentDecl.bindings[0];
const Symbol& symbIn = current.scope->findSymbol(varIn);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
Value* elIn = it->get(index, varEl);
CompilePass::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(elIn, std::move(varEl));
return unitLoop->compile();
}
case xreate::Operator::NONE: {
assert(currentDecl.__state==Expression::IDENT);
const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
return it->get(index);
};
default: break;
}
if (linkedlist){
return index;
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value* move(Value* index, const std::string& hintRetVar) override{
switch(sourceDecl.op)
{
case xreate::Operator::LIST:
case xreate::Operator::LIST_RANGE:
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
default: break;
}
if (linkedlist){
ExpandedType tySource = llvm->ast->expandType(sourceScope->findDefinition(source));
assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
assert(tySource->__operands.size());
return Instructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
}
assert(false && "Unknown declaration");
return nullptr;
}
};
Iterator*
Iterator::create(CompilePass::Context context, const Symbol& var){
const Implementation& data = Query::queryImplementation(var);
switch(data.impl){
case ON_THE_FLY:
return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
default: assert(true);
}
assert(false && "Unknown declaration");
return nullptr;
}
diff --git a/cpp/src/instructions/instr-containers.h b/cpp/src/compilation/instr-containers.h
similarity index 93%
rename from cpp/src/instructions/instr-containers.h
rename to cpp/src/compilation/instr-containers.h
index 9465d35..5651085 100644
--- a/cpp/src/instructions/instr-containers.h
+++ b/cpp/src/compilation/instr-containers.h
@@ -1,86 +1,87 @@
#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* compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
+ llvm::Value* compileLoopContext(const Expression& expression, const std::string& hintRetVar);
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/compilation/latecontext.cpp b/cpp/src/compilation/latecontext.cpp
new file mode 100644
index 0000000..9269b4a
--- /dev/null
+++ b/cpp/src/compilation/latecontext.cpp
@@ -0,0 +1,151 @@
+/*
+ * LateContext.cpp
+ *
+ * Created on: Jan 8, 2016
+ * Author: pgess
+ */
+
+#include "pass/compilepass.h"
+#include "compilation/latecontext.h"
+#include "query/context.h"
+#include "llvmlayer.h"
+
+namespace xreate {
+
+LateContext::LateContext(const std::string& function, CompilePass* compilePass)
+ : pass(compilePass), domain(&compilePass->queryContext->getFunctionDomain(function))
+{}
+
+LateContext::~LateContext()
+{}
+
+llvm::Value*
+LateContext::compileCheckContext(const Expression& e){
+// llvm::Value* environment;
+// LLVMLayer* llvm;
+//
+// PackedExpression rep = __context.pack(e);
+// assert(storage.count(rep));
+//
+// size_t id = storage.at(rep);
+// //TODO determine short name of expression
+// return llvm->builder.CreateExtractElement(environment, id, NAME("checkContext"+e.getValueString()));
+
+ return nullptr;
+}
+
+llvm::Value*
+LateContext::findFunction(const std::string name, ScopePacked scopeOuter, llvm::Function* functionOuter){
+ LLVMLayer* llvm = pass->man->llvm;
+ ContextQuery* queryContext = pass->queryContext;
+ const FunctionSpecializations& specializations = queryContext->getFunctionSpecializations(name);
+
+ //check external function
+ if (!specializations.size()){
+ return nullptr;
+ }
+
+ const std::list<Expression>& context = queryContext->getContext(scopeOuter);
+
+ boost::optional<ManagedFnPtr> variant;
+ for(const Expression& c: context){
+ if (specializations.count(c)){
+ assert(!variant);
+ variant = specializations.at(c);
+ }
+ }
+
+ if (variant) {
+ return pass->getFunctionUnit(*variant)->compile();// RETURN compiled function unit
+ }
+
+ //require default variant if no appropriate static context exists
+ assert(specializations.count(Expression()));
+ llvm::Value* funcDefault = pass->getFunctionUnit(specializations.at(Expression()))->compile();
+
+ //choose default variant if no late context exists
+ if (!domain->size()) {
+ return funcDefault;
+ }
+
+ //RUNTIME PART
+ llvm::BasicBlock *blockCurrent = llvm->builder.GetInsertBlock();
+ llvm::BasicBlock *blockEnd = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationEnd", functionOuter);
+
+ llvm->builder.SetInsertPoint(blockEnd);
+ llvm::Type* tyFuncCallee = funcDefault->getType();
+ llvm::PHINode *ret = llvm->builder.CreatePHI(tyFuncCallee, domain->size(), "callee");
+
+
+ //check runtime context
+ for (const Expression& c: *domain){
+ if (specializations.count(c)){
+ ///if (domain[c]) return specialization.at(c) else
+ llvm->builder.SetInsertPoint(blockCurrent);
+ llvm::Value* cond;
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationNext", functionOuter);
+ llvm->builder.CreateCondBr(cond, blockEnd, blockNext);
+ ret->addIncoming(pass->getFunctionUnit(specializations.at(c))->compile(), blockCurrent);
+ blockCurrent = blockNext;
+ }
+ }
+
+ //check default variant in runtime
+ llvm->builder.SetInsertPoint(blockCurrent);
+ llvm->builder.CreateBr(blockEnd);
+ ret->addIncoming(funcDefault, blockCurrent);
+
+ llvm->builder.SetInsertPoint(blockEnd);
+ return ret;
+}
+
+llvm::Value*
+LateContext::compileArgument(const std::string& callee, ScopePacked scopeOuter){
+ LLVMLayer* llvm = pass->man->llvm;
+
+ std::unordered_set<size_t> indexContextStatic;
+ list<Expression> listContextStatic = pass->queryContext->getContext(scopeOuter);
+ const ContextDomain* calleeDomain = &pass->queryContext->getFunctionDomain(callee);
+
+ llvm::Type* tyBool = llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ llvm::Type* tyInt32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ llvm::Value* result = llvm->builder.CreateAlloca(tyBool, llvm::ConstantInt::get(tyInt32, calleeDomain->size()));
+ llvm::Value* valueTrue = llvm::ConstantInt::get(tyBool, 1);
+ llvm::Value* valueFalse = llvm::ConstantInt::get(tyBool, 0);
+
+ for (const Expression& e: listContextStatic){
+ auto i = calleeDomain->getExpressionId(e);
+ if (i){
+ result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, *i), valueTrue);
+ indexContextStatic.insert(*i);
+ }
+ }
+
+ for (size_t i=0, size=calleeDomain->size(); i<size; ++i){
+ const Expression& e = calleeDomain->get(i);
+ if (indexContextStatic.count(i))
+ continue;
+
+ auto posPrev = domain->getExpressionId(e);
+ if (posPrev){
+ llvm::Value* element = llvm->builder.CreateExtractElement(raw, llvm::ConstantInt::get(tyInt32, *posPrev));
+ result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, i), element);
+ continue;
+ }
+
+ result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, i), valueFalse);
+ }
+
+ return result;
+}
+
+//void
+//LateContext::set(const Expression& e){
+// PackedExpression representation = __context.pack(e);
+//
+// assert(__context.count(representation) == 0);
+// __context.emplace(move(representation), __context.size());
+//}
+
+} /* namespace xreate */
diff --git a/cpp/src/compilation/latecontext.h b/cpp/src/compilation/latecontext.h
new file mode 100644
index 0000000..2ccfe41
--- /dev/null
+++ b/cpp/src/compilation/latecontext.h
@@ -0,0 +1,43 @@
+/*
+ * LateContext.h
+ *
+ * Created on: Jan 8, 2016
+ * Author: pgess
+ */
+
+#ifndef SRC_COMPILATION_LATECONTEXT_H_
+#define SRC_COMPILATION_LATECONTEXT_H_
+
+#include "ast.h"
+#include "expressionserializer.h"
+
+namespace llvm {
+ class Value;
+}
+
+namespace xreate {
+typedef unsigned int ScopePacked;
+
+class CompilePass;
+class ContextDomain;
+
+class LateContext{
+
+public:
+ LateContext(const std::string& function, CompilePass* compilePass);
+ ~LateContext();
+
+ llvm::Value* compileCheckContext(const Expression& e);
+ llvm::Value* compileArgument(const std::string& callee, ScopePacked scopeOuter);
+ llvm::Value* findFunction(const std::string name, ScopePacked scopeOuter, llvm::Function* functionOuter);
+
+ const ContextDomain* const domain;
+ llvm::Value* raw;
+
+private:
+ CompilePass* pass;
+};
+
+} /* namespace xreate */
+
+#endif /* SRC_COMPILATION_LATECONTEXT_H_ */
diff --git a/cpp/src/contextrule.cpp b/cpp/src/contextrule.cpp
new file mode 100644
index 0000000..cea1272
--- /dev/null
+++ b/cpp/src/contextrule.cpp
@@ -0,0 +1,52 @@
+/*
+ * contextrule.cpp
+ *
+ * Created on: Jan 2, 2016
+ * Author: pgess
+ */
+
+#include "contextrule.h"
+#include "clasplayer.h"
+
+#include <boost/format.hpp>
+
+using namespace xreate;
+using namespace std;
+
+ContextRule::ContextRule(const Expression& rule) {
+ assert(rule.op == Operator::CONTEXT_RULE);
+ assert(rule.operands.size() == 3);
+
+ head = rule.operands.at(0);
+ guards = rule.operands.at(1);
+ body = rule.operands.at(2);
+}
+
+std::string
+ContextRule::compile(const ScopePacked& scopeId) const{
+
+ const string prolog =
+ " %context rule visibility implemenetation\n"
+ " context_rule_visibility(X, Y) :- X=Y, scope(X), scope(Y).\n"
+ " context_rule_visibility(X, Y) :- cfa_parent(X, scope(Y)), scope(X), scope(Y).";
+
+ list<string>repHead_ = ClaspLayer::compile(head);
+ assert(repHead_.size() == 1);
+
+ list<string>repGuards_ = ClaspLayer::compile(guards);
+ assert(repGuards_.size() == 1);
+
+ list<string>repBody_ = ClaspLayer::compile(body);
+ assert(repBody_.size() == 1);
+
+ const std::string& atomBindingScope = Config::get("clasp.bindings.scope");
+ boost::format formatContextVisibility("context_rule_visibility(ScopeX, %1%)");
+ boost::format formatScopeBind(atomBindingScope + "(ScopeX, %1%)");
+
+ const string& repHead = str(formatScopeBind % repHead_.front());
+ const string& repGuards = str(formatScopeBind % repGuards_.front());
+ const string& repVisibility = str(formatContextVisibility % scopeId);
+
+ boost::format formatRule("%1%:- %2%, %3%, %4%.");
+ return prolog + str(formatRule % repHead % repGuards % repBody_.front() % repVisibility);
+}
diff --git a/cpp/src/contextrule.h b/cpp/src/contextrule.h
new file mode 100644
index 0000000..7d06e3b
--- /dev/null
+++ b/cpp/src/contextrule.h
@@ -0,0 +1,30 @@
+/*
+ * contextrule.h
+ *
+ * Created on: Jan 2, 2016
+ * Author: pgess
+ */
+
+#ifndef SRC_CONTEXTRULE_H_
+#define SRC_CONTEXTRULE_H_
+
+#include "ast.h"
+#include <string>
+
+namespace xreate {
+
+typedef unsigned int ScopePacked;
+
+class ContextRule {
+ public:
+ ContextRule(const Expression& rule);
+ std::string compile(const ScopePacked& scopeId) const;
+
+ private:
+ Expression head;
+ Expression guards;
+ Expression body;
+};
+}
+
+#endif /* SRC_CONTEXTRULE_H_ */
diff --git a/cpp/src/expressionserializer.cpp b/cpp/src/expressionserializer.cpp
new file mode 100644
index 0000000..34d67c2
--- /dev/null
+++ b/cpp/src/expressionserializer.cpp
@@ -0,0 +1,231 @@
+/*
+ * expressionserializer.cpp
+ *
+ * Created on: Jan 4, 2016
+ * Author: pgess
+ */
+
+#include <expressionserializer.h>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/bimap.hpp>
+#include <boost/bimap/multiset_of.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+
+using namespace std;
+using namespace boost::bimaps;
+namespace xreate {
+
+struct Index {
+ string name;
+ size_t degree; //count of parameters
+ unsigned char level; //level in expression tree (depth of tree layer)
+
+ bool operator< (const Index other) const{
+ if (name != other.name) return name < other.name;
+ if (degree != other.degree) return degree < other.degree;
+ if (name != other.name) return level < other.level;
+ return false;
+ }
+};
+
+class ExpressionSerializerPrivate {
+ boost::bimap<Index, multiset_of<size_t>> __registry;
+ map<unsigned char, size_t> __range;
+
+public:
+ void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){
+ if (!target) return;
+
+ switch (e.op){
+ case Operator::NONE: {
+ switch (e.__state) {
+ case Expression::STRING:
+ case Expression::IDENT: {
+ Index index{e.getValueString(), 0, level};
+ if (!__registry.left.count(index)){
+ target = boost::none;
+ return;
+ }
+
+ size_t id = __registry.left.at(index);
+ size_t range = __range[level];
+ (*target) << make_pair(id, range);
+ return;
+ }
+ default: break;
+ }
+ break;
+ }
+
+ case Operator::CALL: {
+ Index index{e.getValueString(), e.operands.size(), level};
+ if(__registry.left.count(index)){
+ target = boost::none;
+ return;
+ }
+
+ size_t id = __registry.left.at(index);
+ size_t range = __range[level];
+ (*target) << make_pair(id, range);
+
+ for (const Expression& operand: e.operands){
+ pack(operand, level+1, target);
+ }
+ return;
+ }
+ default: break;
+ }
+
+ assert(false && "Expression too complicate for serialization");
+ }
+
+ void registerExpression(const Expression&e, unsigned char level){
+ switch (e.op){
+ case Operator::CALL: {
+ Index index{e.getValueString(), e.operands.size(), level};
+ if (__registry.left.insert(make_pair(index, __range[level])).second){
+ __range[level]++;
+ }
+
+ for (const Expression& operand: e.operands){
+ registerExpression(operand, level+1);
+ }
+ return;
+ }
+
+ case Operator::NONE: {
+ switch (e.__state) {
+ case Expression::STRING:
+ case Expression::IDENT: {
+ Index index{e.getValueString(), 0, level};
+ if (__registry.left.insert(make_pair(index, __range[level])).second){
+ __range[level]++;
+ }
+ return;
+ }
+ default: break;
+ }
+ break;
+ }
+
+ default: break;
+ }
+
+ assert(false && "Expression too complicate for serialization");
+ }
+};
+
+ExpressionSerializer::ExpressionSerializer()
+ : strategy(new ExpressionSerializerPrivate()){
+}
+
+ExpressionSerializer::~ExpressionSerializer() {
+ delete strategy;
+}
+
+void
+ExpressionSerializer::registerExpression(const Expression&e){
+ strategy->registerExpression(e, 0);
+}
+
+PackedExpression
+ExpressionSerializer::pack(const Expression& e){
+ OptionalPackedExpression result;
+ strategy->pack(e, 0, result);
+ assert(result);
+ return move(*result);
+}
+
+OptionalPackedExpression
+ExpressionSerializer::packOptional(const Expression& e) const{
+ OptionalPackedExpression result;
+ strategy->pack(e, 0, result);
+ return result;
+}
+
+void
+PackedExpression::operator<< (const std::pair<size_t, size_t>& value){
+ static const size_t sizeSizeT = sizeof(size_t);
+
+ const size_t& id = value.first;
+ const size_t& range = value.second;
+
+ int countSufficientBits = range <=1? 0 : ceil(log2(range));
+
+ if (0 < countRemainedBits && countRemainedBits < countSufficientBits) {
+ size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
+ (*tail) += id >> (countSufficientBits - countRemainedBits);
+ countSufficientBits-=countRemainedBits;
+ countRemainedBits = 0;
+ }
+
+ if (countRemainedBits == 0) {
+ if (countSufficientBits == 0) return;
+
+ char* __storageNew = new char[size+sizeSizeT];
+ std::memcpy (__storageNew, __storage, size);
+ std::memset(__storageNew + size, 0, sizeSizeT);
+
+ delete[] __storage;
+ __storage = __storageNew;
+
+ size += sizeSizeT;
+ countRemainedBits = 8 * sizeSizeT;
+ }
+
+ if (countRemainedBits >= countSufficientBits) {
+ size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
+ (*tail) += id << (countRemainedBits - countSufficientBits);
+ countRemainedBits -= countSufficientBits;
+ return;
+ }
+
+ assert("Unreachable block");
+}
+
+PackedExpression::PackedExpression(PackedExpression&& other){
+ __storage = other.__storage;
+ size = other.size;
+ countRemainedBits = other.countRemainedBits;
+
+ other.__storage = nullptr;
+}
+
+bool
+PackedExpression::operator==(const PackedExpression& other) const{
+ if (size == other.size && countRemainedBits == other.countRemainedBits){
+ return std::memcmp(__storage, other.__storage, size) == 0 ;
+ }
+
+ return false;
+}
+
+bool
+PackedExpression::operator<(const PackedExpression& other) const{
+ if (size < other.size) { return true; }
+ if (countRemainedBits < other.countRemainedBits) return true;
+
+ if (size == other.size && countRemainedBits == other.countRemainedBits){
+ return std::memcmp(__storage, other.__storage, size) < 0 ;
+ }
+
+ return false;
+}
+
+bool
+PackedExpression::operator!=(const PackedExpression& other) const{
+ return ! ((*this) == other);
+}
+
+PackedExpression::~PackedExpression() {
+ delete[] __storage;
+}
+
+//PackedExpression::PackedExpression (const PackedExpression& other)
+// : size(other.size), countRemainedBits(other.countRemainedBits)
+//{
+// __storage = new char[size];
+// std::memcpy (__storage, other.__storage, size);
+//}
+
+} /* namespace xreate */
diff --git a/cpp/src/expressionserializer.h b/cpp/src/expressionserializer.h
new file mode 100644
index 0000000..910fca9
--- /dev/null
+++ b/cpp/src/expressionserializer.h
@@ -0,0 +1,56 @@
+/*
+ * expressionserializer.h
+ *
+ * Created on: Jan 4, 2016
+ * Author: pgess
+ */
+
+#ifndef SRC_EXPRESSIONSERIALIZER_H_
+#define SRC_EXPRESSIONSERIALIZER_H_
+
+#include "ast.h"
+#include <string>
+#include <boost/optional.hpp>
+
+namespace xreate {
+
+struct PackedExpression{
+ PackedExpression(){};
+ PackedExpression(PackedExpression&& other);
+ ~PackedExpression();
+ void operator<< (const std::pair<size_t, size_t>& value);
+ char* operator*(){return __storage;}
+ bool operator==(const PackedExpression& other) const;
+ bool operator!=(const PackedExpression& other) const;
+ bool operator<(const PackedExpression& other) const;
+ private:
+ PackedExpression (const PackedExpression&)=delete;
+ PackedExpression& operator=(const PackedExpression&)=delete;
+ PackedExpression& operator=(PackedExpression&&)=delete;
+
+ char* __storage = nullptr;
+ size_t size =0;
+ unsigned char countRemainedBits =0;
+};
+typedef boost::optional<PackedExpression> OptionalPackedExpression;
+
+class ExpressionSerializerPrivate;
+
+class ExpressionSerializer {
+public:
+ ExpressionSerializer();
+ ~ExpressionSerializer();
+ ExpressionSerializer(ExpressionSerializer&& other)
+ : strategy(other.strategy), registry(std::move(other.registry)) {}
+ void registerExpression(const Expression&e);
+ PackedExpression pack(const Expression& e);
+ OptionalPackedExpression packOptional(const Expression& e) const;
+
+private:
+ ExpressionSerializerPrivate* strategy;
+ std::map<PackedExpression, size_t> registry;
+};
+
+} /* namespace xreate */
+
+#endif /* SRC_EXPRESSIONSERIALIZER_H_ */
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 0e34bb4..ca7ce01 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,246 +1,255 @@
#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>
+#include <cmath>
using namespace llvm;
using namespace xreate;
using namespace std;
LLVMLayer::LLVMLayer(AST* root)
: ast(root), builder(getGlobalContext()) {
module = new llvm::Module(root->getModuleName(), llvm::getGlobalContext());
layerExtern = new ExternLayer(this);
layerExtern->init(root);
}
void*
LLVMLayer::getFunctionPointer(llvm::Function* function){
uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
return (void*) entryAddr;
}
void
LLVMLayer::initJit(){
std::string ErrStr;
LLVMInitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::EngineBuilder builder((std::unique_ptr<llvm::Module>(module)));
jit = builder
.setEngineKind(llvm::EngineKind::JIT)
.setErrorStr(&ErrStr)
.setVerifyModules(true)
.create();
}
void
LLVMLayer::print(){
llvm::PassManager<llvm::Module> PM;
PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
PM.run(*module);
}
llvm::BasicBlock*
LLVMLayer::initExceptionBlock(llvm::BasicBlock* blockException){
initExceptionsSupport();
PointerType* tyInt8P = PointerType::getInt8PtrTy(llvm::getGlobalContext());
Value* nullInt8P = llvm::ConstantPointerNull::get(tyInt8P);
builder.SetInsertPoint(blockException);
llvm::Function* fAllocate = module->getFunction("__cxa_allocate_exception");
llvm::Function* fThrow = module->getFunction("__cxa_throw");
auto exception = builder.CreateCall(fAllocate, ConstantInt::get(IntegerType::getInt64Ty(getGlobalContext()), 4));
vector<Value*> throwParams{exception, nullInt8P, nullInt8P};
builder.CreateCall(fThrow, ArrayRef<Value*>(throwParams));
builder.CreateUnreachable();
return blockException;
}
void
LLVMLayer::moveToGarbage(void *o)
{
__garbage.push_back(o);
}
llvm::Type*
LLVMLayer::
toLLVMType(const ExpandedType& ty) const {
std::map<int, llvm::StructType*> empty;
return toLLVMType(ty, empty);
}
llvm::Type*
LLVMLayer::
toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const
{
TypeAnnotation t = ty;
switch (t.__operator)
{
case TypeOperator::ARRAY:
{
assert(t.__operands.size()==1);
TypeAnnotation elTy = t.__operands.at(0);
return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
}
case TypeOperator::STRUCT:
case TypeOperator::TUPLE:
{
assert(t.__operands.size());
std::vector<llvm::Type*> pack_;
pack_.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
[this, &conjuctions](const TypeAnnotation& t){
return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
});
llvm::ArrayRef<llvm::Type*> pack(pack_);
//process recursive types:
if (conjuctions.count(t.conjuctionId)) {
auto result = conjuctions[t.conjuctionId];
result->setBody(pack, false);
return result;
}
return llvm::StructType::get(llvm::getGlobalContext(), pack, false);
};
case TypeOperator::LINK: {
llvm::StructType* conjuction = llvm::StructType::create(llvm::getGlobalContext());
int id = t.conjuctionId;
conjuctions.emplace(id, conjuction);
return conjuction;
};
case TypeOperator::CALL:
{
assert(false);
};
case TypeOperator::CUSTOM:
{
//Look in extern types
clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
return layerExtern->toLLVMType(qt);
};
+ case TypeOperator::VARIANT: {
+ int size = t.fields.size();
+ assert(size);
+
+ int bitcount = ceil(log2(size));
+ return llvm::Type::getIntNTy(llvm::getGlobalContext(), bitcount);
+ }
+
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;
clang::QualType pointee = raw->getPointeeType();
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/main.cpp b/cpp/src/main.cpp
deleted file mode 100644
index a43eeed..0000000
--- a/cpp/src/main.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-int main()
-{
- return 0;
-}
-
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 81667b4..8e4aef4 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,169 +1,176 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
#include "passmanager.h"
#include<iostream>
using namespace std;
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
PassContext&& updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return std::move(context2);
}
~PassContext(){}
};
- class PassManager;
-
class AbstractPassBase {
public:
AbstractPassBase(PassManager* manager);
virtual void run()=0;
virtual void finish();
PassManager* man;
};
template<class Output>
Output defaultValue();
template<class Output>
class SymbolCache: private std::map<Symbol, Output>{
public:
bool isCached(const Symbol& symbol){
return this->count(symbol);
}
Output setCachedValue(const Symbol& symbol, Output&& value){
this->emplace(symbol, value);
return value;
}
Output getCachedValue(const Symbol& symbol){
assert(this->count(symbol));
return this->at(symbol);
}
};
template<>
class SymbolCache<void>: private std::set<Symbol>{
public:
bool isCached(const Symbol& symbol){
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol& symbol){
this->insert(symbol);
}
void getCachedValue(const Symbol& symbol){
}
};
template<class Output>
class AbstractPass: public AbstractPassBase {
private:
SymbolCache<Output> __visitedSymbols;
Output processSymbol(const std::string& ident, PassContext context){
const Symbol& symbol = context.scope->findSymbol(ident);
if (__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
if (CodeScope::hasDeclaration(symbol)) {
PassContext context2 = context;
context2.scope = symbol.scope;
Output&& result = process(CodeScope::findDeclaration(symbol), context2, ident);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
public:
AbstractPass(PassManager* manager)
: AbstractPassBase(manager){}
//NOTE implement processFnCall
virtual void processFnCall(ManagedFnPtr function, PassContext context)
{}
+ virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context)
+ {}
+
virtual void process(ManagedRulePtr rule)
{}
virtual Output process(ManagedFnPtr function){
PassContext context;
context.function = function;
return process(function->getEntryScope(), context);
}
virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
context.scope = scope;
return 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);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL) {
const std::string &calleeName = expression.getValueString();
- ManagedFnPtr callee = man->root->findFunction(calleeName);
- if (callee) processFnCall(callee, context);
+ list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
+ if (callees.size() == 1 && callees.front()){
+ processFnCall(callees.front(), context);
+ } else {
+ for (const ManagedFnPtr& callee: callees){
+ processFnCallUncertain(callee, context);
+ }
+ }
}
break;
case Expression::IDENT:
assert(context.scope);
return processSymbol(expression.getValueString(), context);
default:
break;
}
return defaultValue<Output>();
}
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while (rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while (f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const std::string& ident, PassContext context);
}
#endif
diff --git a/cpp/src/pass/adhocpass.cpp b/cpp/src/pass/adhocpass.cpp
new file mode 100644
index 0000000..61173cf
--- /dev/null
+++ b/cpp/src/pass/adhocpass.cpp
@@ -0,0 +1,80 @@
+/*
+ * adhoc.cpp
+ *
+ * Created on: Nov 28, 2015
+ * Author: pgess
+ */
+
+#include "pass/adhocpass.h"
+#include "query/context.h"
+
+namespace xreate {
+ AdhocScheme*
+ AdhocPass::determineForScope(CodeScope* entry){
+ std::list<Expression> contextStack = queryContext->getContext(man->clasp->pack(entry));
+ AdhocScheme* scheme = nullptr;
+
+ for (const Expression& context: contextStack){
+ if (context.__state != Expression::IDENT) continue;
+
+ if (__schemes.count(context.getValueString())){
+ assert(!scheme && "ambiguous context");
+ scheme = __schemes.at(context.getValueString());
+ }
+ }
+
+ assert(scheme && "Appropriate context not found");
+ return scheme;
+ }
+
+ const TypeAnnotation&
+ AdhocScheme::getResultType(){
+ return __resultType;
+ }
+
+ CodeScope*
+ AdhocScheme::getImplementationForCommand(const std::string& comm) {
+ assert(__commands.count(comm) && "Adhoc not defined");
+ return __commands.at(comm);
+ }
+
+ AdhocScheme::AdhocScheme(const Expression& scheme):
+ __resultType(scheme.type), __context(scheme.getValueString()) {
+
+ Expression cases = scheme.getOperands()[0];
+ for (const Expression& exprCase: cases.getOperands()){
+ CodeScope* blockComm = exprCase.blocks.front();
+ std::string nameCase = blockComm->__body.operands[0].getValueString();
+
+ CodeScope* blockImpl = *(++exprCase.blocks.begin());
+ __commands.emplace(nameCase, blockImpl);
+ }
+ }
+
+ const std::string&
+ AdhocScheme::getContext(){
+ return __context;
+ }
+
+ /*
+ void
+ AdhocPass::process(const Expression& expression, PassContext context, const std::string& varDecl=""){
+ if (expression == Exp)
+ }
+ */
+
+ void
+ AdhocPass::run(){
+ queryContext = reinterpret_cast<ContextQuery*>(man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery));
+
+ auto range = man->root->__interfacesData.equal_range(ASTInterface::Adhoc);
+ for (auto i=range.first; i!= range.second; ++i){
+ AdhocScheme* scheme = new AdhocScheme(i->second);
+ __schemes.emplace(scheme->getContext(), scheme);
+ }
+ }
+}
+
+
+
+
diff --git a/cpp/src/pass/adhocpass.h b/cpp/src/pass/adhocpass.h
new file mode 100644
index 0000000..45877ad
--- /dev/null
+++ b/cpp/src/pass/adhocpass.h
@@ -0,0 +1,50 @@
+/*
+ * adhoc.h
+ *
+ * Created on: Nov 28, 2015
+ * Author: pgess
+ */
+//SECTIONTAG adhoc pass
+#ifndef SRC_INSTRUCTIONS_ADHOC_H_
+#define SRC_INSTRUCTIONS_ADHOC_H_
+
+#include "abstractpass.h"
+
+#ifndef FRIEND_ADHOC_UNITTESTS
+ #define FRIEND_ADHOC_UNITTESTS
+#endif
+
+namespace xreate {
+
+ class ContextQuery;
+
+ class AdhocScheme {
+ public:
+ AdhocScheme(const Expression& scheme);
+ CodeScope* getImplementationForCommand(const std::string& comm);
+ const TypeAnnotation& getResultType();
+ const std::string& getContext();
+
+ private:
+ TypeAnnotation __resultType;
+ std::string __context;
+ std::map<std::string, CodeScope*> __commands;
+ };
+
+ class AdhocPass: public AbstractPass<void> {
+ FRIEND_ADHOC_UNITTESTS
+
+ public:
+ AdhocPass(PassManager* manager): AbstractPass(manager) {}
+ AdhocScheme* determineForScope(CodeScope* entry);
+
+ // virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
+ void run() override;
+
+ private:
+ std::map<std::string, AdhocScheme*> __schemes;
+ ContextQuery* queryContext;
+ };
+}
+
+#endif /* SRC_INSTRUCTIONS_ADHOC_H_ */
diff --git a/cpp/src/pass/cfgpass.cpp b/cpp/src/pass/cfgpass.cpp
index 6c84981..84c62b3 100644
--- a/cpp/src/pass/cfgpass.cpp
+++ b/cpp/src/pass/cfgpass.cpp
@@ -1,73 +1,90 @@
#include "cfgpass.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate;
void
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->setCFAData(move(__context.graph));
return AbstractPass::finish();
}
void
CFGPass::processFnCall(ManagedFnPtr function, PassContext context)
{
ClaspLayer* clasp = man->clasp;
- __context.graph.addLink(clasp->pack(context.scope), function->getName());
+ __context.graph.addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
CFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
+ ClaspLayer* clasp = man->clasp;
+
+ CodeScope* scopeParent = context.scope;
+ ScopePacked scopeId = clasp->pack(scope);
+
+ if (scopeParent){
+ __context.graph.addParentConnection(scopeId, clasp->pack(scopeParent));
+ } else {
+ __context.graph.addParentConnection(scopeId, context.function->getName());
+ }
+
+ //TEST scope annotations
+ //SECTIONTAG context gather scope annotations
+ __context.graph.addScopeAnnotations(scopeId, scope->tags);
+
+ __context.graph.addContextRules(scopeId, scope->contextRules);
+
return AbstractPass::process(scope, context, hintBlockDecl);
}
+//TEST scope annotations via scheme
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());
+ __context.graph.addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFGPass::process(ManagedFnPtr function)
{
- __context.graph.addFunctionNodeTags(function->getName(), function->getAnnotations());
-
+ __context.graph.addFunctionAnnotations(function->getName(), function->getAnnotations());
return AbstractPass::process(function);
}
CFGPass::CFGPass(PassManager* manager)
: AbstractPass(manager)
{}
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 0fde4db..4466ae2 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,457 +1,550 @@
#include "compilepass.h"
#include "clasplayer.h"
#include <ast.h>
#include <iostream>
#include "query/containers.h"
-#include "instructions/instr-containers.h"
+#include "query/context.h"
+#include "compilation/instr-containers.h"
#include "ExternLayer.h"
+#include "pass/adhocpass.h"
+
+#include <boost/optional.hpp>
using namespace std;
using namespace xreate;
using namespace llvm;
+//SECTIONTAG types/convert implementation
+llvm::Value*
+doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, LLVMLayer* 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);
+ }
+ }
+
+ return source;
+}
+
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());
+//SECTIONTAG context-based function specialization
+CompilePass::FunctionUnit*
+CompilePass::CodeScopeUnit::findFunctionUnit(const std::string f){
+ AST* ast = pass->man->root;
- if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
- return llvm->builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
- }
+ const ScopePacked& scopeId = pass->man->clasp->pack(scope);
- if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
- return llvm->builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
- }
+ const std::list<Expression>& context = pass->queryContext->getContext(scopeId);
+ std::unordered_set<string> contextIndex;
+ for (const Expression& c: context){
+ if (c.__state != Expression::IDENT) continue;
+ contextIndex.insert(c.getValueString());
}
- assert(false && "no automatic type conversion possible");
+ ManagedFnPtr function = pass->man->root->findFunctionVariant(f, FunctionSpecializationQuery{contextIndex});
+ if (!function.isValid()) return nullptr;
+
+ return pass->getFunctionUnit(function);
}
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);
+ containers::Instructions instructions = containers::Instructions({function, this, pass});
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());
- }
+ //SECTIONTAG types/convert binary operation
+ right = doAutomaticTypeConversion(right, left->getType(), &l);
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();
-
+ llvm::BasicBlock* blockCurrent = pass->man->llvm->builder.GetInsertBlock();
+ 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);
- }
+ [this](const Expression &operand) {
+ return process(operand);
+ }
);
- FunctionUnit* calleeUnit = pass->getFunctionUnit(string(fname));
+ ScopePacked outerScopeId = pass->man->clasp->pack(this->scope);
+ llvm::Value* callee = this->function->lateContext.findFunction(fname, outerScopeId, function->raw);
// external function
- if (!calleeUnit) {
+ if (!callee) {
llvm::Function* external = pass->man->llvm->layerExtern->lookupFunction(fname);
return l.builder.CreateCall(external, args, hintVarDecl);
}
+ //SECTIONTAG late-context propagation arg
+ size_t calleeDomSize = pass->queryContext->getFunctionDomain(fname).size();
+ if (calleeDomSize){
+ llvm::Value* argLateContext = function->lateContext.compileArgument(fname, outerScopeId);
+ args.push_back(argLateContext);
+ }
+
+ //TODO implement inline functions
+ /*
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);
+ //llvm::Value* callee = calleeUnit->compile();
+ pass->man->llvm->builder.SetInsertPoint(blockCurrent);
return l.builder.CreateCall(callee, args, hintVarDecl);
}
case Operator::IF:
{
return instructions.compileIf(expr, hintVarDecl);
}
case Operator::SWITCH:
{
- return nullptr; //instructions.compileSwitch();
+ return instructions.compileSwitch(expr, hintVarDecl);
+ }
+
+ case Operator::LOOP_CONTEXT:
+ {
+ return instructions.compileLoopContext(expr, hintVarDecl);
+ }
+
+ case Operator::LOGIC_AND: {
+ assert(expr.operands.size() == 1);
+ return process (expr.operands[0]);
}
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 (size_t i=0; i<expr.operands.size(); ++i){
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = 0;
- if (operand.isNone()){
- llvm::Type* tyNullField = tyRecord->getElementType(fieldId);
- result = llvm::UndefValue::get(tyNullField);
-
- } else {
+//TODO Null ad hoc Llvm implementation
+// 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);
}
};
+ //SECTIONTAG adhoc actual compilation
+ case Operator::ADHOC: {
+ assert(function->adhocImplementation && "Adhoc implementation not found");
+ string comm = expr.operands[0].getValueString();
+
+ CodeScope* scope = function->adhocImplementation->getImplementationForCommand(comm);
+ CodeScopeUnit* unitScope = function->getScopeUnit(scope);
+ return unitScope->compile();
+ };
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);
};
+ case Expression::VARIANT: {
+ const ExpandedType& typVariant = pass->man->root->expandType(expr.type);
+ llvm::Type* typRaw = l.toLLVMType(typVariant);
+ int value = expr.getValueDouble();
+ return llvm::ConstantInt::get(typRaw, value);
+ }
+
default: {
break;
}
};
break;
default: break;
}
assert(false);
return 0;
}
llvm::Value*
CompilePass::CodeScopeUnit::compile(const std::string& hintBlockDecl){
if (raw != nullptr) return raw;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
raw = process(scope->__body);
return raw;
}
llvm::Value*
CompilePass::CodeScopeUnit::compileSymbol(const Symbol& s, std::string hintRetVar)
{
CodeScope* scope = s.scope;
CodeScopeUnit* self = function->getScopeUnit(scope);
if (self->__rawVars.count(s.identifier)) {
return self->__rawVars[s.identifier];
}
return self->__rawVars[s.identifier] = self->process(scope->findDeclaration(s), hintRetVar);
}
bool
CompilePass::FunctionUnit::isInline(){
Symbol ret = Symbol{0, function->__entry};
bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
return flagOnTheFly;
}
llvm::Function*
CompilePass::FunctionUnit::compile(){
if (raw != nullptr) return raw;
std::vector<llvm::Type *> types;
LLVMLayer* llvm = pass->man->llvm;
CodeScope* entry = function->__entry;
+ AST* ast = pass->man->root;
std::transform(entry->__args.begin(), entry->__args.end(), std::inserter(types, types.end()),
- [this, llvm, entry](const std::string &arg)->llvm::Type* {
+ [this, llvm, ast, 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)));
+ return llvm->toLLVMType(ast->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));
+ //SECTIONTAG late-context signature type
+ size_t sizeDom = lateContext.domain->size();
+ if (sizeDom) {
+ llvm::Type* tyBool = llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ llvm::Type* tyDom = llvm::ArrayType::get(tyBool, sizeDom);
+ types.push_back(tyDom);
+ }
+
+ //SECTIONTAG adhoc func signature determination
+ llvm::Type* funcResultType;
+ if (function->isPrefunction){
+ AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(pass->man->getPassById(PassId::AdhocPass));
+
+ adhocImplementation = adhocpass->determineForScope(entry);
+ funcResultType = llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
+ } else {
+ funcResultType = llvm->toLLVMType(ast->expandType(entry->__definitions[0]));
+ }
+
+ llvm::FunctionType *ft = llvm::FunctionType::get(funcResultType, types, false);
+
+ raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(function->__name + std::to_string(function.id()), 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));
+ if (sizeDom){
+ fargsI->setName("latecontext");
+ lateContext.raw = fargsI;
+ }
+
+ const std::string&blockName = "entry";
+
+ //SECTIONTAG types/convert function ret value
+ llvm->builder.CreateRet(
+ doAutomaticTypeConversion(
+ entryCompilation->compile(blockName), funcResultType, llvm));
llvm->moveToGarbage(ft);
return raw;
}
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;
- }
+CompilePass::getFunctionUnit(const ManagedFnPtr& function){
+ unsigned int id = function.id();
- if (!functions.count(&*fkey)){
- functions.emplace(&*fkey, std::unique_ptr<FunctionUnit>(new FunctionUnit(fkey, this)));
+ if (!functions.count(id)){
+ FunctionUnit* unit = new FunctionUnit(function, this);
+ functions.emplace(id, std::unique_ptr<FunctionUnit>(unit));
+ return unit;
}
- return functions.at(&*fkey).get();
+ return functions.at(id).get();
}
void
CompilePass::run(){
+ queryContext = reinterpret_cast<ContextQuery*> (man->clasp->getQuery(QueryId::ContextQuery));
+
//Find out main function;
ClaspLayer::ModelFragment model = man->clasp->query(Config::get("function-entry"));
assert(model && "Error: No entry function found");
assert(model->first != model->second && "Error: Ambiguous entry function");
string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model->first->second));
- FunctionUnit* unitMain = getFunctionUnit(move(nameMain));
+ FunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction(){
assert(entry);
return entry;
}
+void
+CompilePass::prepareQueries(ClaspLayer* clasp){
+ clasp->registerQuery(new containers::Query(), QueryId::ContainersQuery);
+ clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
+}
//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/compilepass.h b/cpp/src/pass/compilepass.h
index a135d6c..ab199a4 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,82 +1,85 @@
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include "abstractpass.h"
#include "llvm/IR/Function.h"
+#include "compilation/latecontext.h"
namespace xreate {
+class AdhocScheme;
+class ClaspLayer;
+class ContextQuery;
-class CompilePass : public AbstractPass<void>
-{
-public:
+class CompilePass : public AbstractPass<void> {
+ friend class LateContext;
+public:
class CodeScopeUnit;
class FunctionUnit{
public:
FunctionUnit(ManagedFnPtr f, CompilePass* p)
- : function(f), pass(p) {}
+ : function(f), lateContext(f->getName(), p), pass(p) {}
llvm::Value* compileInline(std::vector<llvm::Value*>&& args, CompilePass::FunctionUnit* outer);
bool isInline();
llvm::Function* compile();
CodeScopeUnit* getEntry();
CodeScopeUnit* getScopeUnit(CodeScope* scope);
CodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
ManagedFnPtr function;
llvm::Function* raw = nullptr;
+ AdhocScheme* adhocImplementation=nullptr; //SECTIONTAG adhoc prefunc scheme declaration
+ LateContext lateContext;
+
private:
CompilePass* pass;
std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
};
class CodeScopeUnit {
public:
CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
void bindArg(llvm::Value* var, std::string&& name);
std::map<VID,llvm::Value*> __rawVars;
+ void reset(){raw = nullptr;}
llvm::Value* compile(const std::string& hintBlockDecl="");
llvm::Value* compileSymbol(const Symbol& s, std::string hintRetVar="");
llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="");
CodeScope* scope;
private:
CompilePass* pass;
llvm::Value* raw = nullptr;
FunctionUnit* function;
- llvm::Value* convertType(llvm::Value* source, llvm::Type* tyTarget);
+ FunctionUnit* findFunctionUnit(const std::string f);
};
struct Context{
FunctionUnit* function;
CodeScopeUnit* scope;
CompilePass* pass;
};
- struct FunctionQuery{
- FunctionQuery(std::string&& functionName): name(functionName) {}
-
- std::string name;
- };
-
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
- FunctionUnit* getFunctionUnit(const FunctionQuery& f);
+ FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
void run() override;
llvm::Function* getEntryFunction();
+ static void prepareQueries(ClaspLayer* clasp);
private:
- std::map<Function*, std::unique_ptr<FunctionUnit>> functions;
+ std::map<unsigned int, std::unique_ptr<FunctionUnit>> functions;
llvm::Function* entry = 0;
-
+ ContextQuery* queryContext;
};
}
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfgpass.cpp b/cpp/src/pass/dfgpass.cpp
index 5520d2f..da501ad 100644
--- a/cpp/src/pass/dfgpass.cpp
+++ b/cpp/src/pass/dfgpass.cpp
@@ -1,187 +1,182 @@
#include "dfgpass.h"
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
using namespace std;
namespace xreate{
DFGPass::DFGPass(PassManager* manager)
: AbstractPass(manager), clasp(man->clasp)
{}
SymbolNode
-DFGPass::process(ManagedFnPtr function){
- SymbolNode symbolRet = AbstractPass::process(function);
-
- if (SymbolPacked* symbolRetPacked = boost::get<SymbolPacked>(&symbolRet)){
- Expression retExpr(Operator::CALL, {Atom<Identifier_t>(Config::get("clasp.ret.symbol")),
- Atom<Identifier_t>(boost::str(boost::format("(%1%, %2%)")
- %(symbolRetPacked->identifier)
- % (symbolRetPacked->scope)))
- });
-
- const std::vector<Tag> tag{{retExpr, TagModifier::NONE}};
- clasp->cfagraph.addFunctionNodeTags(function->getName(), tag);
-
- } else if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
- std::vector<Tag> tags;
- tags.reserve(symbT->tags.size());
-
- const std::string stmntRetTag = Config::get("clasp.ret.tag");
- std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
- [&stmntRetTag](const Expression& e) {
- Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
- return Tag{e, TagModifier::NONE};
- });
-
- clasp->cfagraph.addFunctionNodeTags(function->getName(), tags);
+DFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
+ /*
+ 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.addFunctionAnnotations(function->getName(), tags);
}
+ */
- return SymbolInvalid();
+ const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
+ const SymbolPacked& retFormal{0, clasp->pack(scope)};
+ __context.graph.addConnection(retFormal, retActual, DFGConnection::ALIAS);
+
+ return retFormal;
}
SymbolNode
DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
// write down adhoc expression tags:
if (expression.tags.size() && decl.length()) {
for (pair<std::string, Expression> tag: expression.tags) {
SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
- __context.graph.addTag(nodeThis, Expression(tag.second));
+ __context.graph.addAnnotation(nodeThis, Expression(tag.second));
}
}
switch(expression.__state) {
case Expression::IDENT: {
const string& ident = expression.getValueString();
SymbolNode nodeFrom = AbstractPass::process(expression, context, decl);
SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident), context.function->getName() + ":" + ident);
- __context.graph.addLink(nodeTo, nodeFrom, DFGConnection::ALIAS);
+ __context.graph.addConnection(nodeTo, nodeFrom, DFGConnection::ALIAS);
return nodeTo;
}
default: break;
}
- //special case for NONE value:
- if (expression.isNone()){
- return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
- }
-
+//TODO Null ad hoc DFG implementation
+// if (expression.isNone()){
+// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
+// }
switch(expression.op) {
case Operator::CALL: {
const string &name = expression.getValueString();
std::vector<SymbolNode> operands;
operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
- ManagedFnPtr function = man->root->findFunction(name);
- if (!function) return SymbolInvalid();
+ //TODO implement processFnCall/Uncertain
+ list<ManagedFnPtr> functions = man->root->getFunctionVariants(name);
+ if (functions.size()!=1) return SymbolInvalid();
+ ManagedFnPtr function= functions.front();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
std::vector<SymbolNode>::iterator nodeActual = operands.begin();
for (const std::string &identFormal: scopeRemote->__args) {
const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
- __context.graph.addLink(clasp->pack(symbolFormal, name + ":" + identFormal), *nodeActual, DFGConnection::OPT);
+ __context.graph.addConnection(clasp->pack(symbolFormal, name + ":" + identFormal), *nodeActual, DFGConnection::OPT);
++nodeActual;
}
//TODO need SymbolTransient::connection mark in order to represent OPT connection
return clasp->pack(Symbol{0, scopeRemote}, name + ": *retv");
}
default: break;
}
SymbolNode result = AbstractPass::process(expression, context, decl);
if (expression.__state != Expression::COMPOUND){
return result;
}
std::vector<SymbolNode> operands;
if (__signatures.count(expression.op)) {
const Expression &scheme = __signatures.at(expression.op);
operands.reserve(expression.getOperands().size());
if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
string caption = expression.getValueString();
operands.push_back(process(Expression(move(caption)), context, ""));
}
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
std::vector<SymbolNode>::iterator arg = operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
- __context.graph.addTag(*arg, Expression(*tag));
+ __context.graph.addAnnotation(*arg, Expression(*tag));
}
++arg; ++tag;
}
Expression retTag = *scheme.getOperands().begin();
if (retTag.__state != Expression::INVALID) {
- __context.graph.addTag(result, move(retTag));
+ __context.graph.addAnnotation(result, move(retTag));
}
}
// adhoc for MAP case, TODO reorganize code in more clear manner
if (expression.op == Operator::MAP) {
SymbolNode nodeFrom;
if (operands.size()) {
nodeFrom = operands.at(0);
} else {
nodeFrom = process(expression.getOperands().at(0), context);
}
assert(!decl.empty());
SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
assert(nodeFromPacked);
- __context.graph.addLink(move(nodeTo), *nodeFromPacked, DFGConnection::PROTO);
+ __context.graph.addConnection(move(nodeTo), *nodeFromPacked, DFGConnection::PROTO);
}
return result;
}
void
DFGPass::run()
{
init();
return AbstractPass::run();
}
void
DFGPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
__signatures.emplace(scheme.op, scheme);
}
}
void DFGPass::finish()
{
man->clasp->addDFAData(move(__context.graph));
}
template<>
SymbolNode defaultValue(){return SymbolInvalid();};
}
diff --git a/cpp/src/pass/dfgpass.h b/cpp/src/pass/dfgpass.h
index fcf9cf1..d29ecf3 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"
namespace xreate {
class ClaspLayer;
class DFGPass : public AbstractPass<SymbolNode> {
public:
- SymbolNode process(ManagedFnPtr function);
+ SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="");
SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
DFGPass(PassManager* manager);
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/logging.cpp b/cpp/src/pass/loggerpass.cpp
similarity index 76%
rename from cpp/src/pass/logging.cpp
rename to cpp/src/pass/loggerpass.cpp
index 0daaf05..b6fe477 100644
--- a/cpp/src/pass/logging.cpp
+++ b/cpp/src/pass/loggerpass.cpp
@@ -1,106 +1,106 @@
/*
* logging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
-#include "logging.h"
-#include "instructions/instr-containers.h"
+#include <pass/loggerpass.h>
+#include "compilation/instr-containers.h"
#include "utils.h"
using namespace std;
using namespace llvm;
namespace xreate {
-void Logging::init(ClaspLayer* clasp){
+void LoggerPass::init(ClaspLayer* clasp){
auto model = clasp->query(Config::get("logging.id"));
if(!model) return;
for (ClaspLayer::ModelIterator rec = model->first; rec!=model->second; ++rec){
std::tuple<SymbolPacked> _v =ClaspLayer::parse<SymbolPacked>(rec->second);
Symbol v = clasp->unpack(get<0>(_v));
SymbolAttachments::put<IsLogging>(v, true);
}
}
void
-Logging::process(const Expression& expression, PassContext context, const std::string& varDecl){
+LoggerPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (varDecl.size()){
Symbol v = context.scope->findSymbol(varDecl);
if (SymbolAttachments::get<IsLogging>(v, false)){
- CompilePass::FunctionUnit* f = compiler->getFunctionUnit(CompilePass::FunctionQuery(string(context.function->getName())));
- CompilePass::CodeScopeUnit* u = f->getScopeUnit(context.scope);
+ CompilePass::FunctionUnit* func = compiler->getFunctionUnit(context.function);
+ CompilePass::CodeScopeUnit* scope = func->getScopeUnit(context.scope);
- CompilePass::Context compilation{f, u, compiler};
- inject(v, compilation);
+ CompilePass::Context compilationContext{func, scope, compiler};
+ inject(v, compilationContext);
}
}
return AbstractPass<void>::process(expression, context, varDecl);
}
-void Logging::inject(const Symbol& symbol, const CompilePass::Context& context){
+void LoggerPass::inject(const Symbol& symbol, const CompilePass::Context& context){
llvm::Value* source = context.scope->compileSymbol(symbol);
ExpandedType typSource = man->root->expandType(CodeScope::findDefinition(symbol));
string format = "";
switch (typSource->__value) {
case TypePrimitive::Int : case TypePrimitive::Num : case TypePrimitive::I32: case TypePrimitive::I8:
format = "%d\n";
break;
case TypePrimitive::String:
format = "%s\n";
break;
default:
assert(false && "No appropriate type for logging");
}
containers::Instructions compiler(context);
LLVMLayer* llvm = context.pass->man->llvm;
llvm->builder.SetInsertPoint(*source->use_begin());
llvm::Value* formatRaw = compiler.compileConstantStringAsPChar(format, "logformat");
llvm->builder.CreateCall2(refPrintf, formatRaw, source);
}
void
-Logging::initOutput(){
+LoggerPass::initOutput(){
LLVMLayer* llvm = man->llvm;
refPrintf = llvm->module->getFunction("printf");
if (!refPrintf) {
PointerType* typPtrI8 = PointerType::get(IntegerType::get(llvm->module->getContext(), 8), 0);
std::vector<Type*>argsPrintf{typPtrI8};
FunctionType* signaturePrintf = FunctionType::get(
/*Result=*/IntegerType::get(llvm->module->getContext(), 32),
/*Params=*/argsPrintf,
/*isVarArg=*/true);
refPrintf = llvm::Function::Create(
/*Type=*/signaturePrintf,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"printf", llvm->module); // (external, no body)
refPrintf->setCallingConv(CallingConv::C);
}
}
-Logging::Logging(PassManager* manager)
+LoggerPass::LoggerPass(PassManager* manager)
: AbstractPass<void>(manager)
{
initOutput();
init(man->clasp);
}
void
-Logging::initDependencies(CompilePass* pass){
+LoggerPass::initDependencies(CompilePass* pass){
compiler = pass;
}
} /* namespace xreate */
diff --git a/cpp/src/pass/logging.h b/cpp/src/pass/loggerpass.h
similarity index 89%
rename from cpp/src/pass/logging.h
rename to cpp/src/pass/loggerpass.h
index 4745a06..bfa3d0b 100644
--- a/cpp/src/pass/logging.h
+++ b/cpp/src/pass/loggerpass.h
@@ -1,44 +1,44 @@
/*
* logging.h
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#ifndef SRC_LOGGING_H_
#define SRC_LOGGING_H_
#include "ast.h"
#include <llvm/IR/Value.h>
#include "pass/compilepass.h"
#include "pass/abstractpass.h"
#include "clasplayer.h"
namespace xreate {
-class Logging:public AbstractPass<void>, public IQuery {
+class LoggerPass:public AbstractPass<void>, public IQuery {
public:
void inject(const Symbol& symbol, const CompilePass::Context& context);
- Logging(PassManager* manager);
+ LoggerPass(PassManager* manager);
virtual void init(ClaspLayer* clasp);
void initDependencies(CompilePass* pass);
virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
private:
CompilePass* compiler = nullptr;
llvm::Function* refPrintf;
void initOutput();
};
struct IsLogging{};
template<>
struct AttachmentsDict<IsLogging> {
typedef bool Data;
static const unsigned int key = 5;
};
} /* namespace xreate */
#endif /* SRC_LOGGING_H_ */
diff --git a/cpp/src/passmanager.cpp b/cpp/src/passmanager.cpp
index 3bcfded..87d8b8d 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager.cpp
@@ -1,93 +1,102 @@
#include <pass/abstractpass.h>
+#include <pass/loggerpass.h>
#include "query/containers.h"
#include "passmanager.h"
#include "pass/compilepass.h"
+#include "pass/adhocpass.h"
#include "Parser.h"
#include "pass/cfgpass.h"
#include "pass/dfgpass.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);
CFGPass* passCFG = new CFGPass(man);
- man->registerPass(new DFGPass(man), passCFG);
- man->registerPass(passCFG);
+ //TODO is it really DFGPass needs CFGpass?
+ man->registerPass(new DFGPass(man), PassId::DFGPass, passCFG);
+ man->registerPass(passCFG, PassId::CFGPass);
+ man->registerPass(new AdhocPass(man), PassId::AdhocPass);
+
+ CompilePass::prepareQueries(man->clasp);
return man;
}
-
-
void
-PassManager::registerPass(AbstractPassBase* pass, AbstractPassBase* parent)
+PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
{
- __passes.emplace(parent, pass);
+ __passes.emplace(id, pass);
+ __passDependencies.emplace(parent, pass);
+}
+
+AbstractPassBase*
+PassManager::getPassById(const PassId& id){
+ assert(__passes.count(id));
+ return __passes[id];
}
void*
PassManager::run()
{
runWithoutCompilation();
CompilePass* compiler = new CompilePass(this);
compiler->run();
//Compiler Dependents:
- Logging* logger = new Logging(this);
+ LoggerPass* logger = new LoggerPass(this);
logger->initDependencies(compiler);
logger->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
void PassManager::runWithoutCompilation(){
std::list<AbstractPassBase*> passes{nullptr};
while (passes.size()){
AbstractPassBase* parent = passes.front();
- auto range = __passes.equal_range(parent);
+ auto range = __passDependencies.equal_range(parent);
for (auto i=range.first; i!=range.second; ++i){
AbstractPassBase* pass = i->second;
pass->run();
pass->finish();
passes.push_back(pass);
}
passes.pop_front();
}
- clasp->registerdQuery(new containers::Query());
clasp->run();
}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index 4c9e0de..389487f 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,33 +1,45 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include "Scanner.h"
#include <string>
#include <map>
namespace xreate {
class AbstractPassBase;
class ClaspLayer;
class LLVMLayer;
class AST;
+enum class PassId {
+ CFGPass,
+ CompilePass,
+ DFGPass,
+ EnvironmentTestsPass,
+ LoggerPass,
+ AdhocPass,
+ RulesPass
+};
+
class PassManager
{
public:
~PassManager();
- void* run();
+ void*run();
void runWithoutCompilation();
- void registerPass(AbstractPassBase* pass, AbstractPassBase* prerequisite=nullptr);
+ void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr);
+ AbstractPassBase* getPassById(const PassId& id);
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::multimap<AbstractPassBase*, AbstractPassBase*> __passes;
+ std::map<PassId, AbstractPassBase*> __passes;
+ std::multimap<AbstractPassBase*, AbstractPassBase*> __passDependencies;
}; }
#endif
diff --git a/cpp/src/query/context.cpp b/cpp/src/query/context.cpp
new file mode 100644
index 0000000..0f4399b
--- /dev/null
+++ b/cpp/src/query/context.cpp
@@ -0,0 +1,129 @@
+/*
+ * adhoc.cpp
+ *
+ * Created on: Dec 1, 2015
+ * Author: pgess
+ */
+
+#include <query/context.h>
+#include <boost/range/iterator_range_core.hpp>
+
+using namespace std;
+namespace xreate {
+
+std::list<Expression>
+ContextQuery::getContext(const ScopePacked& scopeId){
+ std::list<Expression> result;
+
+ for (auto i: boost::make_iterator_range(__modelContext.equal_range(scopeId))){
+ result.push_back(i.second);
+ }
+
+ for (auto i: boost::make_iterator_range(__modelForcedContext.equal_range(scopeId))){
+ result.push_back(i.second);
+ }
+
+ return result;
+}
+
+void
+ContextQuery::forceContext(const ScopePacked& scopeId, std::list<Expression> context){
+ // TODO remove forced context only of the same class, possibly
+
+ //remove any previous forced context for this scopeId
+ __modelForcedContext.erase(scopeId);
+
+ std::transform(context.begin(), context.end(), inserter(__modelForcedContext, __modelForcedContext.end()),
+ [scopeId](const Expression& context){return make_pair(scopeId, context);});
+}
+
+void
+ContextQuery::init(ClaspLayer* clasp){
+ const std::string& atomEarlyBinding = Config::get("clasp.bindings.scope");
+ ClaspLayer::ModelFragment model = clasp->query(atomEarlyBinding);
+
+ if (model){
+ for (auto i = model->first; i!=model->second; ++i){
+ ScopePacked idScope;
+ Expression context;
+ tie(idScope, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
+ __modelContext.emplace(idScope, context);
+ }
+ }
+
+ const std::string& atomLateBinding = Config::get("clasp.bindings.scope_weak");
+ model = clasp->query(atomEarlyBinding);
+
+ std::map<std::string, std::vector<Expression>> modelLateContext;
+ if (model){
+ for (auto i = model->first; i!=model->second; ++i){
+ string nameFunction;
+ Expression context;
+ tie(nameFunction, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
+ modelLateContext.at(nameFunction).push_back(context);
+ }
+
+ for(auto& entry: modelLateContext){
+ __modelFunctionContext.emplace(entry.first, move(entry.second));
+ }
+ }
+}
+
+const ContextDomain&
+ContextQuery::getFunctionDomain(const std::string& name) const {
+ static ContextDomain domainNULL({});
+
+ if (__modelFunctionContext.count(name)){
+ return __modelFunctionContext.at(name);
+ }
+
+ return domainNULL;
+}
+
+ContextDomain::ContextDomain(const std::vector<Expression>&& expressions)
+ : std::vector<Expression>(move(expressions)){
+ for (const Expression& e: expressions){
+ serializer.registerExpression(e);
+ }
+
+ size_t id =0;
+ for (const Expression& e: expressions){
+ scheme.emplace(serializer.pack(e), id++);
+ }
+}
+
+size_t
+ContextDomain::size() const{
+ return PARENT::size();
+}
+
+
+ContextDomain::const_iterator
+ContextDomain::begin() const {
+ return begin();
+}
+
+ContextDomain::const_iterator
+ContextDomain::end() const {
+ return end();
+}
+
+boost::optional<size_t>
+ContextDomain::getExpressionId(const Expression& e) const{
+ const auto& exprPacked = serializer.packOptional(e);
+ if (!exprPacked){
+ return boost::none;
+ }
+
+ if (scheme.count(*exprPacked)){
+ return scheme.at(*exprPacked);
+ }
+
+ return boost::none;
+}
+
+const Expression&
+ContextDomain::get(size_t id) const{
+ return at(id);
+}
+} /* namespace xreate */
diff --git a/cpp/src/query/context.h b/cpp/src/query/context.h
new file mode 100644
index 0000000..6da9f9d
--- /dev/null
+++ b/cpp/src/query/context.h
@@ -0,0 +1,81 @@
+/*
+ * adhoc.h
+ *
+ * Created on: Dec 1, 2015
+ * Author: pgess
+ */
+
+#ifndef SRC_QUERY_CONTEXT_H_
+#define SRC_QUERY_CONTEXT_H_
+
+#include "clasplayer.h"
+#include "ast.h"
+#include "expressionserializer.h"
+#include <unordered_map>
+namespace xreate {
+
+class ContextDomain: private std::vector<Expression>{
+ typedef std::vector<Expression> PARENT;
+
+public:
+ ContextDomain(const std::vector<Expression>&& expressions);
+ ContextDomain(ContextDomain&& other)
+ : scheme(std::move(other.scheme)), serializer(std::move(serializer)){}
+ boost::optional<size_t> getExpressionId(const Expression& e) const;
+ const Expression& get(size_t id) const;
+ size_t size() const;
+ ContextDomain::const_iterator begin() const;
+ ContextDomain::const_iterator end() const;
+
+private:
+ ContextDomain(const ContextDomain&)=delete;
+
+ std::map<PackedExpression, size_t> scheme;
+ ExpressionSerializer serializer;
+};
+
+template <typename ATTACHMENTS>
+class ContextAttachments: private std::unordered_map<size_t, ATTACHMENTS> {
+ typedef std::unordered_map<size_t, ATTACHMENTS> PARENT;
+
+public:
+ size_t size() const {
+ return PARENT::size();
+ }
+
+ size_t count(const Expression& e) const {
+ return (domain.getExpressionId(e)? 1: 0);
+ }
+
+ const ATTACHMENTS& at(const Expression& e) const{
+ auto id = domain.getExpressionId(e);
+ assert(id);
+ return PARENT::at(*id);
+ }
+
+private:
+ ContextDomain domain;
+};
+typedef ContextAttachments<ManagedFnPtr> FunctionSpecializations ;
+
+class ContextQuery: public IQuery {
+public:
+ //AdhocQuery();
+ std::list<Expression> getContext(const ScopePacked& scopeId);
+ void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
+ const ContextDomain& getFunctionDomain(const std::string& name) const;
+ const FunctionSpecializations& getFunctionSpecializations(const std::string& name) const;
+
+ virtual void init(ClaspLayer* clasp);
+ virtual ~ContextQuery(){};
+private:
+ std::multimap<ScopePacked, Expression> __modelContext;
+ std::multimap<ScopePacked, Expression> __modelForcedContext;
+ std::map<std::string, ContextDomain> __modelFunctionContext;
+ std::map<std::string, FunctionSpecializations> __modelFunctionSpecializations;
+
+};
+
+} /* namespace xreate */
+
+#endif /* SRC_QUERY_CONTEXT_H_ */
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index 925023c..2778ad0 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,130 +1,134 @@
#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)
+ AddTag(const Source &src)
: __src(src) { }
+ explicit
+ AddTag(Source &&src)
+ : __src(std::move(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/skipdetection.cpp b/cpp/tests/adhoc-skipdetection.cpp
similarity index 100%
rename from cpp/tests/skipdetection.cpp
rename to cpp/tests/adhoc-skipdetection.cpp
diff --git a/cpp/tests/adhoc.cpp b/cpp/tests/adhoc.cpp
new file mode 100644
index 0000000..5719e57
--- /dev/null
+++ b/cpp/tests/adhoc.cpp
@@ -0,0 +1,157 @@
+/*
+ * adhoc-exceptions.cpp
+
+ *
+ * Created on: Nov 19, 2015
+ * Author: pgess
+ */
+
+class Adhoc_pass_Adhoc1_Test;
+#define FRIEND_ADHOC_UNITTESTS \
+ friend class ::Adhoc_pass_Adhoc1_Test;
+
+
+#include "ast.h"
+#include "passmanager.h"
+
+#include "gtest/gtest.h"
+#include <stdio.h>
+#include <memory>
+#include <sstream>
+#include <stdlib.h>
+
+
+#include "pass/adhocpass.h"
+#include "pass/compilepass.h"
+#include "llvmlayer.h"
+
+using namespace xreate;
+using namespace std;
+
+TEST(Adhoc, ast_operatorAdhoc1){
+ PassManager* man = PassManager::prepareForCode (
+ " test = "
+ "function:: int {\n"
+ " ad hoc Exception(NonImplemented)\n"
+ " }"
+ );
+
+ Expression subject = man->root->findFunction("test")->getEntryScope()->__body;
+ ASSERT_EQ(Operator::ADHOC, subject.op);
+ ASSERT_EQ(1, subject.getOperands().size());
+
+ Expression exception = subject.getOperands()[0];
+ ASSERT_EQ("Exception", exception.getValueString());
+}
+
+TEST(Adhoc, ast_schemeAdhoc1){
+ PassManager* man = PassManager::prepareForCode (
+ "interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case Error {false}\n"
+ " case Success {true}\n"
+ " }\n"
+ " }");
+
+ assert(man->root->__interfacesData.count(ASTInterface::Adhoc));
+ Expression adhocData = man->root->__interfacesData.find(ASTInterface::Adhoc)->second;
+ ASSERT_EQ(Operator::SWITCH, adhocData.operands[0].op);
+}
+
+TEST(Adhoc, pass_Adhoc1){
+ PassManager* man = PassManager::prepareForCode (
+ "interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case Error {false}\n"
+ " case Success {true}\n"
+ " }\n"
+ " }");
+
+ man->runWithoutCompilation();
+ AdhocPass* pass = reinterpret_cast<AdhocPass* >(man->getPassById(PassId::AdhocPass));
+ EXPECT_TRUE(pass->__schemes.size() > 0);
+
+ AdhocScheme* scheme = pass->__schemes.begin()->second;
+ EXPECT_EQ("expectNoErrors", scheme->getContext());
+}
+
+TEST(Adhoc, full_1){
+ PassManager* man = PassManager::prepareForCode (
+ " import raw (\"core/control-context.lp\")"
+
+ " interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case Error {0}\n"
+ " case Success {1}\n"
+ " }\n"
+ " }"
+
+ " test1 = pre function {\n"
+ " context:: expectNoErrors."
+ " ad hoc \"Success\"\n"
+ " }"
+
+ "main = function::bool;entry {\n"
+ " test1()\n"
+ " }");
+
+ bool (*main)() = (bool (*)()) man->run();
+ bool result = main();
+ ASSERT_EQ(true, result);
+}
+
+TEST(Adhoc, full_contextExpectNoErrrors){
+ PassManager* man = PassManager::prepareForCode (
+ " import raw (\"core/control-context.lp\")\n"
+
+ "interface(extern-c){\n"
+ " xml2 = library:: pkgconfig(\"libxml-2.0\").\n"
+ " \n"
+ " include {\n"
+ " xml2 = [\"stdlib.h\"]\n"
+ " }.\n"
+ "}"
+
+ " interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case Error {0}\n"
+ " case Success {1}\n"
+ " }\n"
+ " }\n"
+
+ " expectErrorCode = pre function(x::int){\n"
+ " if (x==0)::bool {ad hoc \"Success\"}\n"
+ " else {ad hoc \"Error\"}\n"
+ " }\n"
+
+ " main = function::bool; entry {\n"
+ " context:: expectNoErrors."
+ " expectErrorCode(system(\"ls -la\"))\n"
+ " }" );
+
+ int (*main)() = (int (*)()) man->run();
+ ASSERT_EQ(1, main());
+}
+
+TEST(Adhoc, ast_switchAdhoc1){
+ PassManager* man = PassManager::prepareForCode (
+ "test1 = function:: bool {\n"
+ " switch ad hoc (x:: errors)\n"
+ " case ERROR {0}\n"
+ " case SUCCESS {1}\n"
+ " \n"
+ " }"
+ );
+
+ Expression eSwitch = man->root->findFunction("test1")->getEntryScope()->__body;
+ EXPECT_EQ(Operator::SWITCH_ADHOC, eSwitch.op);
+ EXPECT_EQ(3, eSwitch.operands.size());
+
+ EXPECT_EQ(1, eSwitch.tags.size());
+ EXPECT_EQ("errors", eSwitch.tags.begin()->first);
+
+ Expression eCondition = eSwitch.getOperands()[0];
+ EXPECT_EQ("x", eCondition.getValueString());
+}
+
+
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
new file mode 100644
index 0000000..485a7c1
--- /dev/null
+++ b/cpp/tests/context.cpp
@@ -0,0 +1,198 @@
+/*
+ * frame-context.cpp
+ *
+ * Created on: Dec 3, 2015
+ * Author: pgess
+ */
+
+#include "passmanager.h"
+#include "query/context.h"
+
+#include "gtest/gtest.h"
+
+using namespace xreate;
+
+TEST(Context, frame_Context1){
+ PassManager* man = PassManager::prepareForCode(
+ " import raw (\"core/control-context.lp\")\n"
+ " testC = function::int {\n"
+ " context:: testC.\n"
+
+ " 0\n"
+ " }\n"
+
+ " testA = function:: int {\n"
+ " context:: testA; test.\n"
+
+ " testC()\n"
+ " }\n"
+
+ " testB = function:: int {\n"
+ " context:: testB; test.\n"
+
+ " testC()\n"
+ " }\n"
+ );
+
+ ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
+ man->runWithoutCompilation();
+
+ CodeScope* scopeTestC = man->root->findFunction("testC")->getEntryScope();
+ const std::list<Expression>& context = query->getContext(man->clasp->pack(scopeTestC));
+
+ int contextSize = context.size();
+ EXPECT_EQ(2, contextSize);
+}
+
+TEST(Context, full_ContextBasedFunctionSpecialization){
+
+ PassManager* man = PassManager::prepareForCode(
+ " case context::toMillimeters {\n"
+ " convert = function(source:: num)::num {\n"
+ " 10 * source \n"
+ " }\n"
+ " }\n"
+
+ " case context::toInches {\n"
+ " convert = function(source:: num)::num {\n"
+ " 2 * source \n"
+ " }\n"
+ " }\n"
+
+ "test = function(vrnt:: int)::int; entry {\n"
+ " switch(vrnt):: int\n"
+ " case 0 {\n"
+ " context:: toMillimeters.\n"
+ " convert(1)\n"
+ " }\n"
+ "\n"
+ " case 1 {\n"
+ " context:: toInches.\n"
+ " convert(1)\n"
+ " }\n"
+ " case default {0}\n"
+ " }" );
+
+ int (*main)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(10, main(0));
+ ASSERT_EQ(2, main(1));
+}
+
+TEST(Context, full_LoopContext){
+
+ PassManager* man = PassManager::prepareForCode("case context:: a {\n"
+ " print = function:: string {\n"
+ " \"a\"\n"
+ " }}\n"
+ "\n"
+ " case context:: b {\n"
+ " print = function:: string {\n"
+ " \"b\"\n"
+ " }}\n"
+ "\n"
+ " case context:: c {\n"
+ " print = function:: string {\n"
+ " \"c\"\n"
+ " }}\n"
+ "\n"
+ " case context:: d {\n"
+ " print = function:: string {\n"
+ " \"d\"\n"
+ " }}\n"
+ "\n"
+ " start = function(command::int)::string; entry {\n"
+ " switch (command) :: string \n"
+ " case 0 {\n"
+ " context:: print(a); print(b); print(d).\n"
+ "\n"
+ " loop context (\"print\") {\n"
+ " print()\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " case default {\n"
+ " context:: print(c).\n"
+ " loop context (\"print\") {\n"
+ " print()\n"
+ " }\n"
+ " }\n"
+ " }");
+
+
+ char* (*main)(int) =(char* (*)(int)) man->run();
+ ASSERT_STREQ("c", main(1));
+ ASSERT_STREQ("a", main(0));
+}
+
+TEST(Context, full_RuleContext){
+ /*
+ "rule context:: childs(Child)\n"
+ " case artefact(Item)\n"
+ " {\n"
+ " artefact_depends(Item, Child)\n"
+ " }";
+ */
+
+ PassManager* man = PassManager::prepareForCode(
+ " case context:: toMilli {\n"
+ " convert = function(length::int)::int{\n"
+ " 10 * length\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " case context:: toCenti {\n"
+ " convert = function(length::int)::int{\n"
+ " length\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " main=function::int; entry {\n"
+ " context:: output(milli).\n"
+ "\n"
+ " rule context::toMilli\n"
+ " case output(milli) {true}\n"
+ "\n"
+ " convert(1)\n"
+ " }" );
+ man->clasp->addRawScript("true.");
+
+ int (*entry)() = (int (*)()) man->run();
+ ASSERT_EQ(10, entry());
+}
+
+TEST(Context, full_InheritedRuleContext){
+ PassManager* man = PassManager::prepareForCode(
+ " import raw (\"core/control-context.lp\") \n"
+
+ " case context:: toMilli {\n"
+ " convert = function(length::int)::int{\n"
+ " 10 * length\n"
+ " }\n"
+ " }\n"
+
+ " case context:: toCenti {\n"
+ " convert = function(length::int)::int{\n"
+ " length\n"
+ " }\n"
+ " }\n"
+ "\n"
+
+ "main = function(comm:: num)::num; entry{\n"
+ " rule context::X case output(X) {true}\n"
+ "\n"
+ " switch (comm)::num \n"
+ " case 0 {\n"
+ " context:: output(toMilli).\n"
+ " convert(1)\n"
+ " }\n"
+ " case default {\n"
+ " context:: output(toCenti).\n"
+ " convert(1)\n"
+ " }\n"
+ " }");
+
+ man->clasp->addRawScript("true.");
+ int (*entry)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(10, entry(0));
+ ASSERT_EQ(1, entry(1));
+}
diff --git a/cpp/tests/diagnostic-messages.cpp b/cpp/tests/diagnostic-messages.cpp
index b46cdf0..5c7c946 100644
--- a/cpp/tests/diagnostic-messages.cpp
+++ b/cpp/tests/diagnostic-messages.cpp
@@ -1,28 +1,32 @@
/*
* diagnostic-messages.cpp
*
* Created on: Oct 27, 2015
* Author: pgess
*/
+#include "passmanager.h"
+#include "pass/dfgpass.h"
+
#include "gtest/gtest.h"
using namespace std;
+using namespace xreate;
TEST(Diagnostic_DFA, DISABLED_recursion1){
- //Error while processing recursion, Should be some diagnostic complaints
+ //Error while processing recursion, There should be some diagnostic complaints
std::string code = \
"test1 = function()::[int] {\n"
" varRecursion = loop map(varRecursion->el:: int)::[int]{\n"
" el\n"
" }.\n"
" \n"
" varRecursion\n"
"}";
- PassManager* man = PassManager::prepareForCode(code);
+ PassManager* man = PassManager::prepareForCode(move(code));
DFGPass* pass = new DFGPass(man);
pass->run();
pass->finish();
}
diff --git a/cpp/tests/expressions.cpp b/cpp/tests/expressions.cpp
new file mode 100644
index 0000000..6b6e732
--- /dev/null
+++ b/cpp/tests/expressions.cpp
@@ -0,0 +1,31 @@
+/*
+ * expressions.cpp
+ *
+ * Created on: Dec 21, 2015
+ * Author: pgess
+ */
+
+#include "passmanager.h"
+#include "gtest/gtest.h"
+
+using namespace std;
+using namespace xreate;
+
+TEST(Expressions, switch1){
+ string&& code =
+ " colors = type variant (RED, BLUE, GREEN).\n"
+ " test = function:: colors; entry {GREEN}"
+
+ "main = function:: int; entry {\n"
+ " switch(test():: color)\n"
+ " case GREEN {0}\n"
+ " case default {1}\n"
+ "}";
+
+ PassManager* man = PassManager::prepareForCode(move(code));
+ int (*main)() = (int (*)()) man->run();
+
+ EXPECT_EQ(0, main());
+}
+
+
diff --git a/cpp/tests/tests.cpp b/cpp/tests/main.cpp
similarity index 100%
rename from cpp/tests/tests.cpp
rename to cpp/tests/main.cpp
diff --git a/cpp/tests/testLogging.cpp b/cpp/tests/pass-Logger.cpp
similarity index 82%
rename from cpp/tests/testLogging.cpp
rename to cpp/tests/pass-Logger.cpp
index a84026a..a1da4c7 100644
--- a/cpp/tests/testLogging.cpp
+++ b/cpp/tests/pass-Logger.cpp
@@ -1,87 +1,87 @@
/*
* testLogging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
+#include <pass/loggerpass.h>
#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){
+TEST(LoggerPass, 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* compiler = new CompilePass(man);
+ compiler->run();
- CompilePass::FunctionUnit* fTest = compilator->getFunctionUnit(CompilePass::FunctionQuery("test"));
+ CompilePass::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("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};
+ CompilePass::Context params{fTest, scopeUnitTest, compiler};
- Logging l(man);
+ LoggerPass 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){
+TEST(LoggerPass, simpleInjection2){
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);
+ LoggerPass* logger = new LoggerPass(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){
+TEST(LoggerPass, 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/cpp/tests/testExpressionSerializer.cpp b/cpp/tests/testExpressionSerializer.cpp
new file mode 100644
index 0000000..9fd30f3
--- /dev/null
+++ b/cpp/tests/testExpressionSerializer.cpp
@@ -0,0 +1,50 @@
+/*
+ * testExpressionSerializer.cpp
+ *
+ * Created on: Jan 4, 2016
+ * Author: pgess
+ */
+
+#include "expressionserializer.h"
+#include "ast.h"
+#include "gtest/gtest.h"
+using namespace xreate;
+using namespace std;
+
+TEST(ExpressionSerializer, pack1){
+ PackedExpression x;
+
+ x << std::make_pair(0xA1, 0x100);
+ size_t* storage = reinterpret_cast<size_t*> (*x);
+ ASSERT_EQ(0xA100000000000000, *storage);
+
+ x << std::make_pair(0x23456, 0x100000);
+ ASSERT_EQ(0xA123456000000000, *storage);
+
+ x << std::make_pair(0x7654321, 0x10000000);
+ ASSERT_EQ(0xA123456765432100, *storage);
+
+
+ x << std::make_pair(0xABBA, 0x10000);
+ storage = reinterpret_cast<size_t*> (*x);
+ ASSERT_EQ(0xA1234567654321AB, *storage);
+ ASSERT_EQ(0xBA00000000000000, *(storage+1));
+}
+
+TEST(ExpressionSerializer, serialize1){
+ Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))});
+ Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))});
+
+ ExpressionSerializer serializer;
+ serializer.registerExpression(a);
+ serializer.registerExpression(b);
+
+ PackedExpression packA = serializer.pack(a);
+ PackedExpression packB = serializer.pack(b);
+ PackedExpression packA2 = serializer.pack(a);
+
+ ASSERT_EQ(packA, packA2);
+ ASSERT_NE(packA, packB);
+}
+
+
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 0967945..9801984 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,130 +1,149 @@
/*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(Types, DependantTypes1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeXmlNode = program->root->findType("XmlNode");
ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator);
ASSERT_EQ(2, typeXmlNode->__operands.size());
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value);
}
TEST(Types, DependantTypes2) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Template = type Template(Leaf) [Leaf, [Leaf[content]]]."
"Concrete = type alias Template(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
}
TEST(Types, TreeType1) {
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
ASSERT_EQ(2, typeConcrete->__operands.size());
ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
auto typeLink = typeConcrete->__operands.at(1).__operands.at(0);
ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId);
}
TEST(Types, TreeType1LLvm){
string&& code = "XmlNode = type alias {\n"
" tag:: string,\n"
" /* attrs:: [string],*/\n"
" content:: string\n"
"}.\n"
""
"Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
"Concrete = type alias Tree(XmlNode).";
std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
ExpandedType typeConcrete = program->root->findType("Concrete");
llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
TEST(Types, ArrayOfExternal1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symb = body->findSymbol("childrenRaw");
const TypeAnnotation& t = CodeScope::findDefinition(symb);
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
}
TEST(Types, ExternType1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symbTree = body->findSymbol("tree");
const TypeAnnotation& t = CodeScope::findDefinition(symbTree);
const ExpandedType& t2 = ast.expandType(t);
EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
}
+TEST(Types, ast_VariantType1){
+ string&& code =
+ " colors = type variant (RED, BLUE, GREEN).\n"
+ " test = function:: colors; entry {GREEN}";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+
+ ExpandedType typ = program->root->findType("colors");
+ EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
+
+ Expression eRed = program->root->findFunction("test")->getEntryScope()->__body;
+ EXPECT_EQ(Expression::VARIANT, eRed.__state);
+
+ const ExpandedType& typ2 = program->root->expandType(eRed.type);
+ EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
+
+ program->run();
+}
+
//TEST string type
diff --git a/problems/basket/dependencies.lp b/problems/basket/dependencies.lp
new file mode 100644
index 0000000..abbe0c4
--- /dev/null
+++ b/problems/basket/dependencies.lp
@@ -0,0 +1,8 @@
+node(a; b; c; d).
+depends(b,a).
+depends(c,a).
+depends(d, a).
+depends(d, c).
+
+level(X, 0) :- not depends(X, _); node(X).
+level(X, LEVEL):- LEVEL = #max{L+1, level(Y, L): level(Y, L), depends(X, Y)}; node(X); LEVEL > 0.
diff --git a/problems/basket/kitchen.lp b/problems/basket/kitchen.lp
new file mode 100644
index 0000000..f9f0fc9
--- /dev/null
+++ b/problems/basket/kitchen.lp
@@ -0,0 +1,13 @@
+room(bedroom; diningroom; kitchen).
+
+%location(bedroom).
+door(bedroom, diningroom).
+door(diningroom, kitchen).
+
+{move(A, B)} :- location(A); door(A, B); room(A); room(B).
+{move(A, B)} :- move(_, A); door(A, B); room(A); room(B).
+
+goal:- location(kitchen).
+goal:- move(_, kitchen).
+
+:- not goal.
diff --git a/scripts/environment-tests/control-context.lp b/scripts/environment-tests/control-context.lp
new file mode 120000
index 0000000..86bd292
--- /dev/null
+++ b/scripts/environment-tests/control-context.lp
@@ -0,0 +1 @@
+/private/prg/code/xreate/core/control-context.lp
\ No newline at end of file
diff --git a/scripts/environment-tests/dependencies.lp b/scripts/environment-tests/dependencies.lp
new file mode 120000
index 0000000..7db9889
--- /dev/null
+++ b/scripts/environment-tests/dependencies.lp
@@ -0,0 +1 @@
+/private/prg/code/xreate/core/dependencies.lp
\ No newline at end of file
diff --git a/scripts/environment-tests/sequence b/scripts/environment-tests/sequence
new file mode 100644
index 0000000..1fc241b
--- /dev/null
+++ b/scripts/environment-tests/sequence
@@ -0,0 +1,62 @@
+include raw "core/dependencies.lp"
+include raw "core/control-context.lp"
+include raw "core/unit-tests.lp"
+
+start = function:: int; entry {
+ context:: goal(artefact(gcc)).
+
+ provideGoals()
+}
+
+provideGoals = function():: int {
+ loop context (goal) {
+ visit_artefact()
+ }
+}
+
+visitArtefact = function(){
+ switch (EXISTS()){
+ case INSTALLED {
+ ad hoc NOACTION
+ }
+
+ case NON_INSTALLED {
+ run [
+ PROVIDE_DEPENDENCIES(),
+ PROVIDE())
+ ]
+ }
+ }
+}
+
+provideDependencies() = function() {
+ rule context {
+ childs(Child) <- artefact(Item); artefact_depends(Item, Child).
+ }
+
+ loop context (childs) {
+ VISIT_ARTEFACT().
+ }
+}
+
+case context:: artefact(subversion) {
+ EXISTS = function() {
+ exec("svn --version"):: ExpectNoErrors; log("Check svn").
+ }
+
+ PROVIDE = function(){
+ exec("sudo apt-get install subversion"):: log("[Subversion] Installation").
+ }
+}
+
+
+// DRAFT
+/*
+ flagIsProvided = if(dictProvided(<item>)) {true} else
+ dictProvided = dictProvided + <item>
+
+expectErrorCode = pre function(x::int){
+ if (x==0)::bool {ad hoc "Success"}
+ else {ad hoc "Error"}
+}
+*/
\ No newline at end of file
diff --git a/scripts/environment-tests/tests-context.lp b/scripts/environment-tests/tests-context.lp
new file mode 100644
index 0000000..8559a15
--- /dev/null
+++ b/scripts/environment-tests/tests-context.lp
@@ -0,0 +1,28 @@
+#include "control-context.lp".
+
+%body
+ function(a).
+ function(b).
+ function(c).
+
+ scope(0..3).
+ cfa_call(0, c).
+ cfa_call(1, c).
+ cfa_parent(0, function(a)).
+ cfa_parent(1, function(b)).
+ cfa_parent(2, function(c)).
+ cfa_parent(3, scope(2)).
+
+ bind_scope(0, weak(a)).
+ bind_scope(1, weak(b)).
+
+ bind_scope(0, hard).
+ bind_scope(1, hard).
+
+%test weak and hard context
+ :- bind_scope(2, weak(_)).
+ :- not bind_scope(2, hard).
+
+%test rules:
+ bind_scope(X, rule) :- bind_scope(X, hard), context_rule_visibility(X, 2).
+ :- not bind_scope(3, rule).
diff --git a/scripts/environment-tests/tests-early_late_binding.lp b/scripts/environment-tests/tests-early_late_binding.lp
new file mode 100644
index 0000000..a59a8fe
--- /dev/null
+++ b/scripts/environment-tests/tests-early_late_binding.lp
@@ -0,0 +1,21 @@
+%body
+ function(a).
+ function(b).
+ function(c).
+ function(d1).
+ function(d2).
+
+
+scope(0..4).
+cfa_parent(0, function(a)).
+cfa_parent(1, function(b)).
+cfa_parent(2, function(c)).
+cfa_parent(3, function(d1)).
+cfa_parent(4, function(d2)).
+
+cfa_call(0, function(c)).
+cfa_call(1, function(c)).
+cfa_call(2, function(d)).
+
+bind_scope(0, a).
+bind_scope(1, b).
\ No newline at end of file
diff --git a/scripts/environment-tests/xreate-environment b/scripts/environment-tests/xreate-environment
index f7428c8..149efed 100644
--- a/scripts/environment-tests/xreate-environment
+++ b/scripts/environment-tests/xreate-environment
@@ -1,60 +1,73 @@
// install cmake
// install llvm
// install gcc
// install gtest
-function():: TestEnvironment(exists(gcc)){
+EXISTS(gcc) = function(){
exec("gcc -v") :: ExpectNoErrors; log("Check gcc").
}
function():: provide(gcc) {
exec("sudo apt-get install gcc"):: log("[GCC] Installation").
}
function():: TestEnvironment(exists(cmake)){
exec("cmake /V"):: ExpectNoErrors; log("Check cmake").
}
function():: provide(cmake) {
exec("sudo apt-get install cmake"):: log("[CMake] Installation").
}
function():: TestEnvironment(exists(subversion)){
exec("svn --version"):: ExpectNoErrors; log("Check svn").
}
function():: provide(subversion) {
exec("sudo apt-get install subversion"):: log("[Subversion] Installation").
}
function():: TestEnvironment(exists(scons)){
exec("scons -v"):: ExpectNoErrors; log("Check scons").
}
function():: provide(scons) {
exec("sudo apt-get install scons"):: log("[Scons] Installation").
}
function():: TestEnvironment(exists(bison)){
exec("bison --version"):: ExpectNoErrors; log("Check bison").
}
function():: provide(bison) {
exec("sudo apt-get install bison"):: log("[Bison] Installation").
}
//FEATURE dependent packages: Subversion
function():: provide(gringo)
{
exec("cd /opt"). //FEATURE states: dir("/opt")
exec("svn://svn.code.sf.net/p/potassco/code/trunk")
:: log("[Potassco] cloning latest version");
require(svn); require(rights("/opt", WRITE)). //"sudo chown -R user ./potassco"
//
exec("scons --build-dir=release"):: require(scons)
}
-function()::{
+function()::depends(env(gringo)){
+
+}
+
+exec(cmd::string) = procedure {
+ system(cmd)::ErrorCodeResult.
}
+
+procedure :: EnvironmentTest(gcc) {
+ exec("gcc -v")::ExpectNoErrors.
+}
+
+EnvironmentProvider(gcc) = procedure {
+ exec("sudo apt-get install gcc"):: log("[GCC] Installation").
+}
\ No newline at end of file
diff --git a/scripts/function-modifications/control-context.lp b/scripts/function-modifications/control-context.lp
deleted file mode 100644
index 22d3247..0000000
--- a/scripts/function-modifications/control-context.lp
+++ /dev/null
@@ -1 +0,0 @@
-function_mod(func1, mod1):- %context condition
diff --git a/scripts/testspass/Containers_Implementation_LinkedList1.xreate b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
index cbc893d..7721ddc 100644
--- a/scripts/testspass/Containers_Implementation_LinkedList1.xreate
+++ b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
@@ -1,47 +1,47 @@
// EXTERN INCLUDES
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["libxml/tree.h"]
}.
}
// CONTAINERS
interface(dfa) {
operator map:: (op(seqaccess)) -> impl(solid).
operator list_range:: ()->impl(on_the_fly).
operator list:: ()->impl(solid).
operator fold:: (op(seqaccess)).
operator index:: (op(randaccess)).
/* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
}
-import raw("core/containers.lp").
+import raw("core/containers.lp")
// PROGRAM
XmlNode = type alias {
tag:: string,
/* attrs:: [string],*/
content:: string
}.
Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
XmlTree = type alias Tree(XmlNode).
-test= function():: num; entry {
+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 {
count +1::int
}.
size
}
diff --git a/scripts/trash/ftransform.li b/scripts/trash/ftransform.li
new file mode 100644
index 0000000..d75c454
--- /dev/null
+++ b/scripts/trash/ftransform.li
@@ -0,0 +1,26 @@
+//преобразование параметров функции
+
+function(first-function, vars-list(var(x, i32), var(y, i32)), i32,
+ div(add(x, 5), y))
+
+--------------------------------------------------------------------------------------------------
+
+type(name(ListNode), struct(
+ field(name(caption), type(String)),
+ field(name(args), type(collection(ListNode)))
+))
+
+
+
+transform(
+ name(f-transform), guard(var(name(X), constraints(caption(simple-function)))),
+ body(
+ set (args, field(X, args),
+
+
+ wrap(extract(args, 0), caption(name)),
+
+ wrap
+ name(field())
+ )
+)
diff --git a/scripts/trash/intersection.li2 b/scripts/trash/intersection.li2
new file mode 100644
index 0000000..6ce957a
--- /dev/null
+++ b/scripts/trash/intersection.li2
@@ -0,0 +1,93 @@
+// пример реализации процедуры определения пересечения двух множеств
+//
+//
+// A, B - два множества
+
+
+Iterator (Set set) : (Set set, int pos)
+
+next(Iterator Set i): action of Iterator{
+ pos++;
+
+ return i;
+}
+
+written El_Type x = Iterator/Set/El_Type i : substitution{
+ x = i.pos;
+}
+
+
+A overtake B: action of Iterator {
+ elB = current (B); //эта команда может превратиться просто в использование elA из вызывающей функции, используя аннотацию context или bag
+
+ repeat-post elA<elB
+ elA = next(A);
+
+ return elA;
+}
+
+intersect(Set A, B) : function, return Set = {
+ A, B : sorted
+ Set RESULT-SET;
+
+with Iterator
+ repeat
+ elA = next(A); // при первом вызове указывает на первый элемент
+ elB = next(B);
+
+ if (elA > elB)
+ elB = B overtake A;
+ else
+ elA = A overake B;
+
+ if (elA == elB)
+ put(RESULT-SET, elA);
+
+return RESULT-SET
+}
+
+// repeat - бесконечный повтор?
+// repeat-pre - повтор с предусловием, repeat-post - повтор с постусловием
+
+
+
+
+ Работа с Map:
+ Пример отображения(view), пример №1:
+
+Map/(KEY, VALUE): type = [(KEY, VALUE)];
+
+Map-T ([KEY], [VALUE]): view, pairs: Map/(KEY, VALUE) = {
+ keys = map pairs, pair
+ (key, ) = pair;
+ key
+
+ values = map pairs, pair
+ (, value) = pair;
+ value
+
+ return (keys, values)
+}
+
+//(SELECT key, SELECT value) - возможно ли в функцию передавать названия поля, с кот. ей нужно работать.. ?
+
+ Пример №2 (свести к поиску 6):
+
+find6: function = {
+x: [int] = [1, 2, 3, 4, 5, 6, 7]; //эффективная инициализация!
+
+y = map x, el
+ 2 * el
+
+return exists(x, 12);
+}
+
+
+/**
+ * Построить:
+ * сортировка :- необходимо ordered-list(linked-list, tree-list)
+ * RA доступ :- желательно hash-list или желательно tree-list
+ * последовательный доступ :- желательно ordered-list
+ *
+ *
+Necessarily and ◇ for Possibly
\ No newline at end of file
diff --git a/scripts/trash/opcode.comments b/scripts/trash/opcode.comments
new file mode 100644
index 0000000..31c457b
--- /dev/null
+++ b/scripts/trash/opcode.comments
@@ -0,0 +1,30 @@
+
+/*
+
+ASTLispNode
+
+
+transform(
+
+ function(__name, __vars), function(name(__name), vars-list(__vars), body(function.body)
+)
+*/
+
+
+add(y, div(add(x, 5), 15))))
+
+
+opcode(add, LLVMAddInstruction)
+opcode(div, LLVMDivideInstruction)
+
+function(name(first-function),
+ vars-list(var(name(x), type(i32)), var(name(y), type(i32))),
+ return(type(i32)),
+ body(
+ div(add(x, 5), y)))
+
+function (name(second-f), vars-list, return(type(i32)), body(
+ add(add (10, 20), first-function(11, 80))
+))
+
+main(second-f)
\ No newline at end of file
diff --git a/scripts/trash/opcode.li b/scripts/trash/opcode.li
new file mode 100644
index 0000000..5f62311
--- /dev/null
+++ b/scripts/trash/opcode.li
@@ -0,0 +1,14 @@
+opcode(add, LLVMAddInstruction)
+opcode(div, LLVMDivideInstruction)
+
+function(name(first-function),
+ vars-list(var(name(x), type(i32)), var(name(y), type(i32))),
+ return(type(i32)),
+ body(
+ div(add(x, 5), y)))
+
+function (name(second-f), vars-list, return(type(i32)), body(
+ add(add (10, 20), first-function(80, 11))
+))
+
+main(second-f)
\ No newline at end of file
Event Timeline
Log In to Comment