No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:33 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index c24f5bc..3bfb0e9 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,515 +1,518 @@
//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 || 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 = (. Function* function; .)
{ ( RuleDecl | InterfaceData | Imprt | ContextSection
| IF(checkFuncDecl()) FDecl<function> (. root.add(function); .)
| TDecl ) }.
Ident<std::wstring& name>
= ident {':' ident} (. name = t->val; .).
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
( 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); .)
+ContextSection<>= (. Expression context; Function* f; .)
+"case" "context" tagcolon MetaSimpExpr<context>
+lcurbrack { FDecl<f> (. f->guardContext = context; root.add(f); .)
} 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, 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); .)
'{' { (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); .)
+(. e = Expression(Operator::IF, {cond}); e.addBlock(blockTrue); e.addBlock(blockFalse); e.bindType(move(typIf)); .)
.
LoopDecl<Expression& e, TypeAnnotation& typOut> =
(. 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, {}); 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> = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); .)
"case"
( "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
exprCase.addBlock(scope);
outer.operands.insert(++outer.operands.begin(), exprCase); .)
| 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>
} (. scope->setBody(guard); popContextScope(); .).
CaseParam<CodeScope* scope, Expression& guard> = (. TypeAnnotation argtyp; Expression condition; .)
(
IF(checkAssignment()) VDecl<scope>
| ExprTyped<condition, argtyp> (. guard.addArg(move(condition)); .)
).
+SequenceDecl<Expression& sequence> =
+"sequence" ListLiteral<sequence> (. sequence.setOp(Operator::SEQUENCE); .).
+
+
/*============================ INTERFACES ===============================*/
Imprt<> =
"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 ===============================*/
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)); root.recognizeVariantIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
- | StructLiteral<e> (. /* struct */.)
+ | StructLiteral<e> (. /* struct */.)
+ | SequenceDecl<e>
| 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 ef2aff4..80e5eb5 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,56 +1,58 @@
{
"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_weak" : "bind_scope_weak"
+ "function_demand" : "bind_function_demand",
+ "scope_decision": "bind_scope_decision"
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
- "template": "adhocs",
+ "template": "installation",
"templates": {
"basic": "EntryFunction*",
"default": "*-",
"types": "Types*-",
"containers": "Containers*-",
"ast": "AST*",
"non-containers": "*-Containers*",
"log": "Logging*",
"clang": "ClangAPI*",
"cfg": "CFG.*",
"skip": "SkipDetection*",
"raw-xml": "libxml2*",
"xml": "Xml.*",
- "adhocs": "ExpressionSerializer.*:Adhoc.*:Context.*"
+ "adhocs": "ExpressionSerializer.*:Adhoc.*:Context.*",
+ "installation": "Compilation.*:Sprint1.*"
}
}
}
diff --git a/core/control-context.lp b/core/control-context.lp
index 1c27c0f..f815057 100644
--- a/core/control-context.lp
+++ b/core/control-context.lp
@@ -1,27 +1,23 @@
-%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_decision(Scope, Fn, Resolution):- cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution), bind_scope(Scope, Resolution).
+bind_scope_decision(Scope, Fn, Resolution):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Fn), cfa_function_specializations(Fn, Resolution), bind_scope(Scope, Resolution).
+
+bind_scope_demand(Scope, FnCallee):- cfa_call(Scope, FnCallee), cfa_function_specializations(FnCallee, _), not bind_scope_decision(Scope, FnCallee, _).
+bind_scope_demand(Scope, FnCallee):- bind_scope_demand(ScopeChild, FnCallee), cfa_parent(ScopeChild, scope(Scope)).
+bind_scope_demand(Scope, FnCallee):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, FnCallee), not bind_scope_decision(Scope, FnCallee, _).
+
+bind_function_demand(Fn, Demand):- bind_scope_demand(Scope, Demand), cfa_parent(Scope, 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)).
+%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).
-
-
+%scope_function(Scope, Fn) :- cfa_parent(Scope, scope(ScopeParent)), scope_function(ScopeParent, Fn).
\ No newline at end of file
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 9630011..909759a 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,174 +1,183 @@
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(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
+ ./src/pass/compilepass.cpp
+ ./src/compilation/latecontextcompiler2.cpp
+
${TEST_FILES}
-
- ./src/ast.cpp
+
+ #./src/compilation/latecontextcompiler.cpp
+
+ ./src/serialization/expressionserializer.cpp
+ ./src/serialization/expressionserializer2.cpp
+ ./src/query/context.cpp
+
+ ./src/ast.cpp
./src/llvmlayer.cpp ./src/clasplayer.cpp
- #./src/main.cpp
- ./src/utils.cpp
+ ./src/utils.cpp
./src/passmanager.cpp
- ./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp ./src/pass/compilepass.cpp
+ ./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp
./src/pass/cfgpass.cpp
./src/pass/loggerpass.cpp
./src/pass/adhocpass.cpp
- #./src/pass/rulespass.cpp
+ #./src/pass/rulespass.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_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(RESOURCES_DBUS_INTERFACES
+ resources/hamster.xml
+)
# 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_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})
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(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
+#cotire(xreate)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 3a866ab..ed57492 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,282 +1,285 @@
//
// Created by pgess on 4/21/15.
//
#include "ExternLayer.h"
#include <cstdio>
#include <iostream>
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/TargetInfo.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
using namespace xreate;
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
class FinderCallbackTypeDecl : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
typeResult = decl->getUnderlyingType();
}
}
};
class FinderCallbackFunction : public MatchFinder::MatchCallback {
public :
QualType typeResult;
virtual void run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
typeResult = decl->getType();
}
}
};
void
ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package)
{
__dictLibraries.emplace(name.get(), package.get());
}
void
ExternData::addIncludeDecl(Expression&& e)
{
assert(e.op == Operator::LIST_NAMED);
//TODO ?? implement Expression parsing(Array of Expr as vector<string>);
for(size_t i=0, size=e.operands.size(); i<size; ++i)
{
std::string library = e.bindings.at(i);
assert(__dictLibraries.count(library));
std::string package = __dictLibraries.at(library);
Expression listHeaders = e.operands.at(i);
assert(listHeaders.op == Operator::LIST);
std::vector<std::string> headers;
std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
[](const Expression& o){
assert(o.__state == Expression::STRING);
return o.getValueString();
});
entries.emplace_back(ExternEntry{package, std::move(headers)});
}
}
void
ExternLayer::addExternalData(const std::vector<ExternEntry>& data){
entries.insert(entries.end(), data.begin(), data.end());
}
ExternLayer::ExternLayer(LLVMLayer *llvm)
: __datalayout(llvm->module), __llvm(llvm)
{}
std::vector<string>
ExternLayer::fetchPackageFlags(const ExternEntry& entry){
std::vector<string> args;
FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
if (linelen==1 && linebuf[0]==' ') continue;
if (linebuf[linelen-1 ] == ' ')
linebuf[linelen-1] = 0;
llvm::outs() << '<' << linebuf << "> ";
args.push_back(linebuf);
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (args);
}
std::vector<string>
ExternLayer::fetchPackageLibs(const ExternEntry& entry){
std::vector<string> libs;
FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
size_t linesize=0;
char* linebuf=0;
ssize_t linelen=0;
while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
if (linebuf[0]=='\n') continue;
if (linelen==1 && linebuf[0]==' ') continue;
if (linebuf[linelen-1 ] == ' ')
linebuf[linelen-1] = 0;
if (linelen>=2 && linebuf[0] == '-' && linebuf[1] == 'l'){
libs.push_back(linebuf + 2);
} else {
libs.push_back(linebuf);
}
llvm::outs() << '<' << linebuf << "> ";
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (libs);
}
void
ExternLayer::loadLibraries(vector<string>&& libs){
string msgErr;
for (const string& lib: libs) {
const string& libName = string("lib")+lib+".so";
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(libName.c_str(), &msgErr)){
llvm::errs()<<"\n"<<"Loading library "<<lib<<". " <<msgErr<<"\n";
}
}
}
void
ExternLayer::init(const AST* root) {
addExternalData(root->__externdata);
// TODO use default include path from 'clang -xc++ -E'
list<string> code;
std::vector<string> args{
"-I/usr/include"
,"-I/usr/local/include"
,"-I/usr/lib/llvm-3.6/lib/clang/3.6.2/include"
// ,"-I/usr/lib/gcc/x86_64-linux-gnu/4.9/include"
// ,"-I/usr/include/x86_64-linux-gnu"
};
std::vector<string> libs;
boost::format formatInclude("#include \"%1%\"");
for(const ExternEntry& entry: entries)
{
llvm::outs()<<"[ExternC] Processing package: "<< entry.package << "\n";
llvm::outs()<<"[ExternC] args: ";
vector<string>&& args2 = fetchPackageFlags(entry);
args.insert(args.end(), args2.begin(), args2.end());
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
llvm::outs()<<"\n[ExternC] libs: ";
args2 = fetchPackageLibs(entry);
for(const string arg: args2) {
llvm::outs()<< "<" << arg << "> ";
}
libs.insert(libs.end(), args2.begin(), args2.end());
llvm::outs()<<"\n[ExternC] headers: ";
std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
[&formatInclude](const string header ) {
string line = boost::str(formatInclude % header);
llvm::outs()<< "<" << line << "> ";
return line;
});
llvm::outs() << '\n';
}
loadLibraries(move(libs));
ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
__cgo.reset(new CodeGenOptions);
__datalayout = llvm::DataLayout(ast->getASTContext().getTargetInfo().getTargetDescription());
__cgm.reset(new CodeGen::CodeGenModule(ast->getASTContext(), *__cgo, *__llvm->module, __datalayout, ast->getASTContext().getDiagnostics()));
};
bool
ExternLayer::isPointer(const clang::QualType &t) {
const clang::Type * tInfo = t.getTypePtr();
assert(tInfo);
return tInfo->isAnyPointerType();
}
llvm::Type*
ExternLayer::toLLVMType(const clang::QualType& t){
return __cgm->getTypes().ConvertType(t);
}
std::vector<std::string>
ExternLayer::getStructFields(const clang::QualType& ty)
{
clang::QualType t = ty;
if (isPointer(ty)){
const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
t = tPtr->getPointeeType();
}
assert(t.getTypePtr()->isRecordType());
const RecordType *record = t->getAsStructureType();
assert(record);
std::vector<std::string> result;
//FieldDecl* field: record->getDecl()->fields()
for (auto i=record->getDecl()->field_begin(); i!= record->getDecl()->field_end(); ++i){
result.push_back(i->getName());
}
return result;
}
clang::QualType
ExternLayer::lookupType(const std::string& id){
MatchFinder finder;
FinderCallbackTypeDecl callbackTypeDecl;
auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
finder.matchAST(ast->getASTContext());
assert(! callbackTypeDecl.typeResult.isNull());
return callbackTypeDecl.typeResult;
}
llvm::Function*
ExternLayer::lookupFunction(const std::string& name){
if (__functions.count(name)){
return __functions.at(name);
}
MatchFinder finder;
FinderCallbackFunction callback;
auto matcher = functionDecl(hasName(name)).bind("function");
finder.addMatcher(matcher, &callback);
finder.matchAST(ast->getASTContext());
- assert(! callback.typeResult.isNull());
+ if (callback.typeResult.isNull()){
+ cout <<"[External Layer] " << "Unknown function: "<<name << endl;
+ assert(false && "Unknown external function");
+ }
const QualType& tyFuncQual = callback.typeResult;
llvm::Type *tyRaw = __cgm->getTypes().ConvertType(tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
llvm::Function* function = llvm::Function::Create(tyRawFunc, llvm::GlobalValue::ExternalLinkage, name, __llvm->module);
__functions.emplace(name, function);
return function;
}
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 2bebce2..6d5f2ad 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,726 +1,701 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <clasplayer.h>
using namespace std;
namespace xreate{
class TypesResolver {
private:
const AST* ast;
std::map<std::string, TypeAnnotation> scope;
std::map<TypeAnnotation, int> signatures;
ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()){
return TypesResolver(ast, scope, signatures)(t, args);
}
std::vector<TypeAnnotation>
expandOperands(const std::vector<TypeAnnotation>& operands) {
std::vector<TypeAnnotation> pack;
pack.reserve(operands.size());
std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation& t){
return expandType(t);
});
return pack;
}
public:
TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
: ast(root), scope(scopeOuter), signatures(signaturesOuter) {
}
ExpandedType
operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>())
{
//assert(args.size() == t.bindings.size()); // invalid number of arguments
for (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(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())
{
}
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();
}
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.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});
+ __indexFunctions.emplace(f->getName(), __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)
{
int count = __indexFunctions.count(name);
if (!count) {
return ManagedFnPtr::Invalid();
}
assert(count ==1);
auto range = __indexFunctions.equal_range(name);
- return ManagedPtr<Function>(range.first->second.id, &this->__functions);
+ return ManagedPtr<Function>(range.first->second, &this->__functions);
}
std::list<ManagedFnPtr>
-AST::getFunctionVariants(const std::string& name){
- auto functions = __indexFunctions.equal_range(name);
+AST::getAllFunctions() const{
+ const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
- std::transform(functions.first, functions.second, inserter(result, result.end()),
- [this](auto f){return ManagedFnPtr(f.second.id, &this->__functions);});
+ for (size_t i=0; i<size; ++i){
+ result.push_back(ManagedFnPtr(i, &this->__functions));
+ }
return result;
}
-ManagedFnPtr
-AST::findFunctionVariant(const std::string& name, const FunctionSpecializationQuery& query) {
- boost::optional<FunctionSpecialization> variant;
- boost::optional<FunctionSpecialization> variantDefault;
-
+//TASK select default specializations
+std::list<ManagedFnPtr>
+AST::getFunctionVariants(const std::string& name) const{
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));
+ std::list<ManagedFnPtr> result;
+ std::transform(functions.first, functions.second, inserter(result, result.end()),
+ [this](auto f){return ManagedFnPtr(f.second, &this->__functions);});
- //case of external functions
- return ManagedFnPtr::Invalid();
+ return result;
}
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
+ std::cout << "Unknown symbol: "<< name << std::endl;
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);
+ //TODO restore addRuleWarning
+ //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 e3ea188..748048c 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,540 +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){
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, 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, LOOP_CONTEXT, INDEX, IF, SWITCH, SWITCH_ADHOC, CASE, CASE_DEFAULT, LOGIC_AND, ADHOC, CONTEXT_RULE
+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, SEQUENCE
};
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() 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 isValid() const;
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, 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
+ //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();
+ std::list<ManagedFnPtr> getAllFunctions() const;
+ std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
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;
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 adc4701..21237f6 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,670 +1,689 @@
#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;
+//TODO escape identifiers started from upper case symbol
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 || *atom.name() == atomBindScope){
string name = *std::get<1>(parse<Gringo::Value, Gringo::Value>(atom)).name();
__model.emplace(move(name), move(atom));
}
__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;
-
+ std::ostringstream bufFunctionNames;
boost::format formatFunction("function(%1%).");
boost::format formatBind(atomBinding + "(%1%, %2%).");
for (auto function: cfagraph.__nodesFunction.left) {
- cout << formatFunction % (function.second) << std::endl;
-
+ const auto tags = cfagraph.__functionTags.equal_range(function.first);
+ if (tags.first == tags.second) {
+ //no tags
+ bufFunctionNames << "; " << function.second ;
+ continue;
+ }
- for (const auto& tag_: boost::make_iterator_range(cfagraph.__functionTags.equal_range(function.first))){
+ cout << formatFunction % (function.second) << std::endl;
+ for (const auto& tag_: boost::make_iterator_range(tags)){
const Tag& tag = tag_.second;
list<string> tagRaw = compile(tag.first);
assert(tagRaw.size() == 1);
cout << formatBind
% (function.second)
% (tagRaw.front())
<< endl;
++counterTags;
}
}
+ if (bufFunctionNames.tellp()){
+ cout << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
+ }
+
if (counterTags == 0) {
- cout << "%no tags at all" << endl;
+ cout << "%no functtion tags at all" << endl;
}
//declare scopes
- boost::format formatScope("scope(%1%).");
- for (auto scope: __indexScopes) {
- //std::string function = scope.first.
- cout << formatScope % scope.second << std::endl;
- }
+ boost::format formatScope("scope(0..%1%).");
+ cout << formatScope % (__registryScopes.size() - 1) << 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(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 % scopeId %(tagRaw.front()) << endl;
++counterTags;
}
if (counterTags == 0) {
cout << "%scope tags: no tags at all" << endl;
}
cout << endl << "%\t\tStatic analysis: CFA" << endl;
//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;
}
+
+ //function specializations descrtiption
+ //SECTIONTAG late-context cfa_function_specializations
+ boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
+ const list<ManagedFnPtr>& functions = ast->getAllFunctions();
+ for (auto f: functions){
+ if (f->guardContext.isValid()){
+ list<string> guardRaw = compile(f->guardContext);
+ assert(guardRaw.size() == 1);
+ cout << formatSpecializations % (f->getName()) % (guardRaw.front()) << 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){
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()),
[](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;
}
//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){
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 (auto q: __queries)
{
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) {
+ ClaspLayer::pack(CodeScope* const 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::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::addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>& tags){
for (Expression tag: tags){
__scopeTags.emplace(scope, tag);
}
}
void
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);
__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->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::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom)
{
auto range = __outEdges.equal_range(identifierFrom);
for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
{
if (__edges[edge->second].second == identifierTo)
return true;
}
return false;
}
void
DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
VisitorAddLink visitor(this, nodeTo, link);
boost::apply_visitor(visitor, nodeFrom);
}
void
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);
}
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 2e208d3..f920106 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,239 +1,239 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_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 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> __parentFunctionRelations;
std::map<ScopePacked, ScopePacked> __parentScopeRelations;
- std::multimap<ScopePacked, unsigned int> __callRelations;
+ std::set<std::pair<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 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();
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);
+ ScopePacked pack(CodeScope* const 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::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);
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/compilation/instr-containers.cpp b/cpp/src/compilation/instr-containers.cpp
index 38192a0..2cbf0a0 100644
--- a/cpp/src/compilation/instr-containers.cpp
+++ b/cpp/src/compilation/instr-containers.cpp
@@ -1,575 +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;
+ compilation::CodeScopeUnit* scope = context.scope; \
+ compilation::FunctionUnit* function = context.function;
-Instructions::Instructions(CompilePass::Context ctx)
+Instructions::Instructions(compilation::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);
+ compilation::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);
+ compilation::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);
+ const ContextDomain& 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);
+ compilation::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::Type* tyResultType = llvm->toLLVMType(llvm->ast->expandType(exprIf.type));
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"));
+ llvm::PHINode *ret = builder.CreatePHI(tyResultType, 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);
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?
+ compilation::CodeScopeUnit* sourceUnit;
+ compilation::FunctionUnit* function; //TODO is used somewhere?
const Expression& sourceDecl;
- CompilePass::Context context;
+ compilation::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)),
+ IteratorForward(compilation::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 compilation::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);
+ compilation::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){
+Iterator::create(compilation::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/compilation/instr-containers.h b/cpp/src/compilation/instr-containers.h
index 5651085..9fe4a08 100644
--- a/cpp/src/compilation/instr-containers.h
+++ b/cpp/src/compilation/instr-containers.h
@@ -1,87 +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);
+ static Iterator* create(compilation::Context context, const Symbol& var);
};
class Instructions {
public:
- Instructions(CompilePass::Context ctx);
+ Instructions(compilation::Context ctx);
llvm::Value* compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string ident = "");
llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
llvm::Value* compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
llvm::Value* 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;
+ compilation::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/latecontextcompiler.cpp
similarity index 55%
rename from cpp/src/compilation/latecontext.cpp
rename to cpp/src/compilation/latecontextcompiler.cpp
index 9269b4a..418b655 100644
--- a/cpp/src/compilation/latecontext.cpp
+++ b/cpp/src/compilation/latecontextcompiler.cpp
@@ -1,151 +1,136 @@
/*
* LateContext.cpp
*
* Created on: Jan 8, 2016
* Author: pgess
*/
-#include "pass/compilepass.h"
-#include "compilation/latecontext.h"
#include "query/context.h"
+#include <compilation/latecontextcompiler.h>
+#include "pass/compilepass.h"
#include "llvmlayer.h"
namespace xreate {
-LateContext::LateContext(const std::string& function, CompilePass* compilePass)
- : pass(compilePass), domain(&compilePass->queryContext->getFunctionDomain(function))
+LateContextCompiler::LateContextCompiler(const std::string& function, CompilePass* compilePass)
+ : pass(compilePass)
{}
-LateContext::~LateContext()
+LateContextCompiler::~LateContextCompiler()
{}
llvm::Value*
-LateContext::compileCheckContext(const Expression& e){
+LateContextCompiler::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
+LateContextCompiler::findFunction(const std::string name, ScopePacked scopeOuter, llvm::Function* functionOuter){
+/*
+ * , functionDomain(&compilePass->queryContext->getFunctionDomain(function))
+ //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");
+ llvm::PHINode *ret = llvm->builder.CreatePHI(tyFuncCallee, functionDomain->size(), "callee");
//check runtime context
- for (const Expression& c: *domain){
- if (specializations.count(c)){
- ///if (domain[c]) return specialization.at(c) else
+ for (const ManagedFnPtr& f: specializations){
+ const Expression& guard = f->guardContext;
+ if (!guard.isValid()) continue;
+
+ if (functionDomain->count(guard)){
+ ///example: if (domain[c]) return specializtion.at(c) else
llvm->builder.SetInsertPoint(blockCurrent);
+ //TASK implement `cond`
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);
+ ret->addIncoming(pass->getFunctionUnit(f)->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;
+
+ */ return nullptr;
}
llvm::Value*
-LateContext::compileArgument(const std::string& callee, ScopePacked scopeOuter){
+LateContextCompiler::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);
+ const ContextDomain& 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* 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);
+ auto i = calleeDomain.getId(e); //TODO it is like iteration 0..size-1, right?
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);
+ 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);
+ auto posPrev = functionDomain->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;
+ */
+
+ return nullptr;
+}
+
+size_t
+LateContextCompiler::getFunctionDomainSize() const {
+ return pass->queryContext->getFunctionDomain(functionName).size();
}
//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/latecontextcompiler.h
similarity index 53%
rename from cpp/src/compilation/latecontext.h
rename to cpp/src/compilation/latecontextcompiler.h
index 2ccfe41..e3f6a2e 100644
--- a/cpp/src/compilation/latecontext.h
+++ b/cpp/src/compilation/latecontextcompiler.h
@@ -1,43 +1,45 @@
/*
* LateContext.h
*
* Created on: Jan 8, 2016
* Author: pgess
*/
-#ifndef SRC_COMPILATION_LATECONTEXT_H_
-#define SRC_COMPILATION_LATECONTEXT_H_
+#ifndef SRC_COMPILATION_LATECONTEXTCOMPILER_H_
+#define SRC_COMPILATION_LATECONTEXTCOMPILER_H_
#include "ast.h"
-#include "expressionserializer.h"
namespace llvm {
class Value;
+ class Function;
}
namespace xreate {
typedef unsigned int ScopePacked;
class CompilePass;
-class ContextDomain;
-class LateContext{
+//SECTIONTAG late-context compilation logic wrt late context
+
+class LateContextCompiler{
public:
- LateContext(const std::string& function, CompilePass* compilePass);
- ~LateContext();
+ LateContextCompiler(const std::string& function, CompilePass* compilePass);
+ ~LateContextCompiler();
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);
+ size_t getFunctionDomainSize() const;
- const ContextDomain* const domain;
- llvm::Value* raw;
+ llvm::Value* raw = nullptr;
private:
+ std::string functionName;
CompilePass* pass;
};
} /* namespace xreate */
-#endif /* SRC_COMPILATION_LATECONTEXT_H_ */
+#endif /* SRC_COMPILATION_LATECONTEXTCOMPILER_H_ */
diff --git a/cpp/src/compilation/latecontextcompiler2.cpp b/cpp/src/compilation/latecontextcompiler2.cpp
new file mode 100644
index 0000000..5dccbc0
--- /dev/null
+++ b/cpp/src/compilation/latecontextcompiler2.cpp
@@ -0,0 +1,119 @@
+/*
+ * LateContextCompiler2.cpp
+ *
+ * Created on: 10 февр. 2016
+ * Author: pgess
+ */
+
+#include "latecontextcompiler2.h"
+#include "llvmlayer.h"
+#include "pass/compilepass.h"
+#include "query/context.h"
+#include <iostream>
+
+namespace xreate {
+
+LateContextCompiler2::LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p)
+ : function(f), pass(p){}
+
+//TEST default variants - do not enable specialization context in order to check default variant invocation
+llvm::Value*
+LateContextCompiler2::findFunction(const std::string& calleeName, llvm::Function* specializationDefault){
+ LLVMLayer* llvm = pass->man->llvm;
+ llvm::IRBuilder<>& builder = llvm->builder;
+ ContextQuery* context = pass->queryContext;
+ const string& functionName = function->function->getName();
+
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
+ const FunctionContextDemand& decisions = context->getFunctionDemand(functionName);
+
+ assert(decisions.right.count(calleeName) && "Can't determine specialization of the function");
+ size_t decisionIndex = decisions.right.at(calleeName);
+ const ContextDomain& decisionDomain= context->getFunctionDomain(calleeName);
+
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyCallee = specializationDefault->getType();
+
+ llvm::BasicBlock* blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", this->function->raw);
+
+ llvm::Value* decisionRaw = builder.CreateExtractValue(this->raw, llvm::ArrayRef<unsigned>{decisionIndex});
+ llvm::SwitchInst* instrSwitch = builder.CreateSwitch(decisionRaw, blockDefault, decisionDomain.size());
+
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationEnd", this->function->raw);
+ builder.SetInsertPoint(blockEpilog);
+ llvm::PHINode *ret = llvm->builder.CreatePHI(tyCallee, decisionDomain.size(), "callee");
+
+ for (const ManagedFnPtr& f: specializations){
+ if (!f->guardContext.isValid()) continue;
+ const Code& specCode = decisionDomain.getId(f->guardContext);
+ llvm::ConstantInt* rawSpecCode = llvm::ConstantInt::get(ty32, specCode);
+
+ llvm::BasicBlock* blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case+" + f->guardContext.getValueString(), this->function->raw);
+ builder.SetInsertPoint(blockCase);
+ builder.CreateBr(blockEpilog);
+ ret->addIncoming(pass->getFunctionUnit(f)->compile(), blockCase);
+
+ instrSwitch->addCase(rawSpecCode, blockCase);
+ }
+
+ //prepare default specialization
+ builder.SetInsertPoint(blockDefault);
+ builder.CreateBr(blockEpilog);
+ ret->addIncoming(specializationDefault, blockDefault);
+
+ builder.SetInsertPoint(blockEpilog);
+ return ret;
+}
+
+llvm::Value*
+LateContextCompiler2::compileArgument(const std::string& callee, ScopePacked scopeOuter){
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ ContextQuery* context = pass->queryContext;
+ const string& functionName = function->function->getName();
+ const map<string, Expression>& dictStaticDecisions = context->getStaticDecisions(scopeOuter);
+
+ const FunctionContextDemand& decisionsCallee = context->getFunctionDemand(callee);
+ const FunctionContextDemand& decisionsSelf = context->getFunctionDemand(functionName);
+
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, decisionsCallee.size());
+
+ //builder.CreateAlloca(tyDemand, llvm::ConstantInt::get(ty32, 1));
+ llvm::Value* res = llvm::ConstantArray::getNullValue(tyDemand);
+
+ for (size_t i=0, size = decisionsCallee.size(); i<size; ++i){
+ const string& key = decisionsCallee.left.at(i);
+
+ if (dictStaticDecisions.count(key)){
+ const Expression& decision = dictStaticDecisions.at(key);
+ const Domain& dom = context->getFunctionDomain(key);
+ const Code& decisionCode = dom.getId(decision);
+
+ res = builder.CreateInsertValue(res, llvm::ConstantInt::get(ty32, decisionCode), llvm::ArrayRef<unsigned>{i});
+ continue;
+ }
+
+ //TEST decision propagtion
+ const size_t& decisionIndex = decisionsSelf.right.at(key);
+ llvm::Value* decision = builder.CreateExtractValue(this->raw, llvm::ArrayRef<unsigned>{decisionIndex});
+ res = builder.CreateInsertElement(res, llvm::ConstantInt::get(ty32, i), decision);
+ }
+
+ return res;
+}
+
+size_t
+LateContextCompiler2::getFunctionVariantsSize() const {
+ ContextQuery* context = pass->queryContext;
+
+ return context->getFunctionDomain(function->function->getName()).size();
+}
+
+size_t
+LateContextCompiler2::getFunctionDemandSize() const {
+ ContextQuery* context = pass->queryContext;
+
+ return context->getFunctionDemand(function->function->getName()).size();
+}
+
+} /* namespace xreate */
diff --git a/cpp/src/compilation/latecontextcompiler2.h b/cpp/src/compilation/latecontextcompiler2.h
new file mode 100644
index 0000000..4ef802a
--- /dev/null
+++ b/cpp/src/compilation/latecontextcompiler2.h
@@ -0,0 +1,50 @@
+/*
+ * LateContextCompiler2.h
+ *
+ * Created on: 10 февр. 2016
+ * Author: pgess
+ */
+
+#ifndef LATECONTEXTCOMPILER2_H_
+#define LATECONTEXTCOMPILER2_H_
+
+#include "serialization.h"
+
+namespace llvm {
+ class Value;
+ class Function;
+}
+
+namespace xreate {
+ class CompilePass;
+
+namespace compilation {
+ class FunctionUnit;
+}}
+
+namespace xreate {
+
+typedef unsigned int ScopePacked;
+class LateContextCompiler2 {
+public:
+ llvm::Value* raw = nullptr;
+
+ LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p);
+ llvm::Value* findFunction(const std::string& calleeName, llvm::Function* specializationDefault);
+ llvm::Value* compileArgument(const std::string& callee, ScopePacked scopeOuter);
+ size_t getFunctionVariantsSize() const;
+ size_t getFunctionDemandSize() const;
+
+private:
+ typedef ExpressionSerialization<RequirementIntegralCode>::Code Code;
+ typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
+ //boost::bimap<size_t, std::string> __decisions;
+ //std::vector<Domain> __scheme;
+
+ compilation::FunctionUnit* function;
+ CompilePass* pass;
+};
+
+} /* namespace xreate */
+
+#endif /* LATECONTEXTCOMPILER2_H_ */
diff --git a/cpp/src/contextrule.cpp b/cpp/src/contextrule.cpp
index cea1272..6ae4fc4 100644
--- a/cpp/src/contextrule.cpp
+++ b/cpp/src/contextrule.cpp
@@ -1,52 +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).";
+ "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).\n";
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/expressionserializer.h b/cpp/src/expressionserializer.h
deleted file mode 100644
index 910fca9..0000000
--- a/cpp/src/expressionserializer.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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/pass/adhocpass.cpp b/cpp/src/pass/adhocpass.cpp
index 61173cf..8473a79 100644
--- a/cpp/src/pass/adhocpass.cpp
+++ b/cpp/src/pass/adhocpass.cpp
@@ -1,80 +1,81 @@
/*
* 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));
+ const ScopePacked scopeId = man->clasp->pack(entry);
+ const ContextDomain& domain = queryContext->getContext(scopeId);
AdhocScheme* scheme = nullptr;
- for (const Expression& context: contextStack){
+ for (const Expression& context: domain){
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/cfgpass.cpp b/cpp/src/pass/cfgpass.cpp
index 84c62b3..120b80d 100644
--- a/cpp/src/pass/cfgpass.cpp
+++ b/cpp/src/pass/cfgpass.cpp
@@ -1,90 +1,98 @@
#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.addCallConnection(clasp->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
+void
+CFGPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){
+ ClaspLayer* clasp = man->clasp;
+ __context.graph.addCallConnection(clasp->pack(context.scope), function->getName());
+
+ return AbstractPass::processFnCallUncertain(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.addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFGPass::process(ManagedFnPtr function)
{
__context.graph.addFunctionAnnotations(function->getName(), function->getAnnotations());
return AbstractPass::process(function);
}
CFGPass::CFGPass(PassManager* manager)
: AbstractPass(manager)
{}
diff --git a/cpp/src/pass/cfgpass.h b/cpp/src/pass/cfgpass.h
index c68ba2f..8640f20 100644
--- a/cpp/src/pass/cfgpass.h
+++ b/cpp/src/pass/cfgpass.h
@@ -1,33 +1,34 @@
// Control Flow Graph determination pass
#ifndef CFGPASS_H
#define CFGPASS_H
#include "passmanager.h"
#include "clasplayer.h"
#include "abstractpass.h"
namespace xreate {
class CFGPass : public AbstractPass<void>
{
public:
void process(ManagedFnPtr function) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
+ void processFnCallUncertain(ManagedFnPtr function, PassContext context) override;
void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
CFGPass(PassManager* manager);
void finish() override;
void run() override;
private:
struct {
CFAGraph graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
}; }
#endif // CFGPASS_H
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 4466ae2..84e1cb5 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,550 +1,654 @@
#include "compilepass.h"
#include "clasplayer.h"
+#include "llvmlayer.h"
#include <ast.h>
-#include <iostream>
+
#include "query/containers.h"
#include "query/context.h"
#include "compilation/instr-containers.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
#include <boost/optional.hpp>
+#include <memory>
+#include <iostream>
using namespace std;
using namespace xreate;
+using namespace xreate::compilation;
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)
+
+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;
-}
+namespace xreate {
-//SECTIONTAG context-based function specialization
-CompilePass::FunctionUnit*
-CompilePass::CodeScopeUnit::findFunctionUnit(const std::string f){
- AST* ast = pass->man->root;
+class CallStatement {
+public:
+ virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>&) = 0;
+};
- const ScopePacked& scopeId = pass->man->clasp->pack(scope);
+class CallStatementRaw: public CallStatement{
+public:
+ CallStatementRaw(llvm::Value* callee): __callee(callee) {}
- 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());
+ llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
+ return builder.CreateCall(__callee, args, hintDecl);
}
- ManagedFnPtr function = pass->man->root->findFunctionVariant(f, FunctionSpecializationQuery{contextIndex});
- if (!function.isValid()) return nullptr;
+private:
+ llvm::Value* __callee;
+};
+
+class CallStatementInline: public CallStatement{
+public:
+ CallStatementInline(FunctionUnit* caller, FunctionUnit* callee)
+ : __caller(caller), __callee(callee) {}
+
+ llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
+ //TEST inlining
+ return __callee->compileInline(move(args), __caller);
+ }
+
+private:
+ FunctionUnit* __caller;
+ FunctionUnit* __callee;
+};
- return pass->getFunctionUnit(function);
+}
+
+//SECTIONTAG late-context find callee function
+//TEST static late context decisions
+//TEST dynamic late context decisions
+CallStatement*
+CodeScopeUnit::findFunction(const std::string& calleeName){
+ LLVMLayer* llvm = pass->man->llvm;
+ ClaspLayer* clasp = pass->man->clasp;
+
+ ContextQuery* queryContext = pass->queryContext;
+
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
+
+ //check external function
+ if (!specializations.size()){
+ llvm::Function* external = pass->man->llvm->layerExtern->lookupFunction(calleeName);
+
+ return new CallStatementRaw(external);
+ }
+
+ //no decisions required
+ if (specializations.size()==1){
+ if (!specializations.front()->guardContext.isValid()) {
+ return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile());
+ }
+ }
+
+ //prepare specializations dictionary
+ typedef ExpressionSerialization<>::Serializer Serializer;
+ typedef ExpressionSerialization<>::Code Code;
+
+ auto adapter = [](const ManagedFnPtr& p){ return p->guardContext; };
+ Serializer serializer(specializations, adapter);
+
+ std::map<Code, ManagedFnPtr> dictSpecializations;
+ boost::optional<ManagedFnPtr> variantDefault;
+ boost::optional<ManagedFnPtr> variant;
+
+ for(const ManagedFnPtr& f: specializations){
+ const Expression& guard = f->guardContext;
+
+ //default case:
+ if (!guard.isValid()){
+ variantDefault = f;
+ continue;
+ }
+
+ assert(dictSpecializations.emplace(serializer.getId(guard), f).second && "Found several appropriate specializations");
+ }
+
+ //check static context
+ const ScopeContextDecisions& decisions = queryContext->getStaticDecisions(clasp->pack(this->scope));
+ if (decisions.count(calleeName)){
+ variant = dictSpecializations.at(serializer.getId(decisions.at(calleeName)));
+ }
+
+ size_t sizeDemand = this->function->contextCompiler.getFunctionDemandSize();
+
+ //decision made if static context found or no late context exists(and there is default variant)
+ bool flagHasStaticDecision = variant || (variantDefault && !sizeDemand);
+
+ //if no late context exists
+ if (flagHasStaticDecision) {
+ FunctionUnit* calleeUnit = pass->getFunctionUnit(variant? *variant: *variantDefault);
+
+ //inlining possible based on static decision only
+ if (calleeUnit->isInline()) {
+ return new CallStatementInline(function, calleeUnit);
+ }
+
+ return new CallStatementRaw(calleeUnit->compile());
+ }
+
+ //require default variant if no static decision made
+ assert(variantDefault);
+
+ llvm::Function* functionVariantDefault = this->pass->getFunctionUnit(*variantDefault)->compile();
+ return new CallStatementRaw(this->function->contextCompiler.findFunction(calleeName, functionVariantDefault));
+}
+
+void
+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::process(const Expression& expr, const std::string& hintVarDecl){
-#define VARNAME(x) (hintVarDecl.empty()? x: hintVarDecl)
+CodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
+#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left; llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
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]);
//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"));
+ return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
case Operator::SUB:
- return l.builder.CreateSub(left, right, VARNAME("tmp_sub"));
+ return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
- return l.builder.CreateMul(left, right, VARNAME("tmp_mul"));
+ return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
- return l.builder.CreateSDiv(left, right, VARNAME("tmp_div"));
+ return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU:
left->dump();
right->dump();
- return l.builder.CreateICmpEQ(left, right, VARNAME("tmp_equ"));
+ return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
break;
case Operator::LSS:
- return l.builder.CreateICmpSLT(left, right, VARNAME("tmp_lss"));
+ return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::GTR:
- return l.builder.CreateICmpSGT(left, right, VARNAME("tmp_gtr"));
+ return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
- return l.builder.CreateNeg(left, VARNAME("tmp_neg"));
+ return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
break;
case Operator::CALL: {
assert(expr.__state == Expression::COMPOUND);
- llvm::BasicBlock* blockCurrent = pass->man->llvm->builder.GetInsertBlock();
+ std::string nameCallee = expr.getValueString();
+ unique_ptr<CallStatement> callee(findFunction(nameCallee));
- std::string fname = expr.getValueString();
+ //prepare arguments
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);
}
);
ScopePacked outerScopeId = pass->man->clasp->pack(this->scope);
- llvm::Value* callee = this->function->lateContext.findFunction(fname, outerScopeId, function->raw);
-
- // external function
- 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);
+ size_t calleeDemandSize = pass->queryContext->getFunctionDemand(nameCallee).size();
+ if (calleeDemandSize){
+ llvm::Value* argLateContext = function->contextCompiler.compileArgument(nameCallee, 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(blockCurrent);
- return l.builder.CreateCall(callee, args, hintVarDecl);
+ return (*callee)(move(args), DEFAULT("res_"+nameCallee), l.builder);
}
case Operator::IF:
{
- return instructions.compileIf(expr, hintVarDecl);
+ return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
- return instructions.compileSwitch(expr, hintVarDecl);
+ return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOOP_CONTEXT:
{
- return instructions.compileLoopContext(expr, hintVarDecl);
+ return instructions.compileLoopContext(expr, DEFAULT("tmp_loop"));
}
case Operator::LOGIC_AND: {
assert(expr.operands.size() == 1);
return process (expr.operands[0]);
}
case Operator::LIST:
{
- return instructions.compileConstantArray(expr, hintVarDecl);
+ return instructions.compileConstantArray(expr, DEFAULT("tmp_list"));
};
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;
//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"));
+ return instructions.compileMapSolid(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
- return instructions.compileFold(expr, VARNAME("fold"));
+ return instructions.compileFold(expr, DEFAULT("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));
+ return instructions.compileArrayIndex(s, indexes, DEFAULT(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::SEQUENCE: {
+ assert (expr.getOperands().size());
+
+ llvm::Value* result;
+ for(const Expression &op: expr.getOperands()){
+ result = process(op, "");
+ }
+
+ return result;
+ }
+
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);
+ return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
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){
+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)
+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(){
+FunctionUnit::isInline(){
Symbol ret = Symbol{0, function->__entry};
bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
return flagOnTheFly;
}
llvm::Function*
-CompilePass::FunctionUnit::compile(){
+FunctionUnit::compile(){
if (raw != nullptr) return raw;
std::vector<llvm::Type *> types;
LLVMLayer* llvm = pass->man->llvm;
+ llvm::IRBuilder<>& builder = llvm->builder;
CodeScope* entry = function->__entry;
AST* ast = pass->man->root;
+ const string& functionName = ast->getFunctionVariants(function->__name).size() > 1? function->__name + std::to_string(function.id()) : function->__name;
+
std::transform(entry->__args.begin(), entry->__args.end(), std::inserter(types, types.end()),
[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(ast->expandType(entry->__definitions.at(argid)));
});
//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);
+ size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
+ if (sizeLateContextDemand) {
+ llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
+ types.push_back(tyDemand);
}
//SECTIONTAG adhoc func signature determination
- llvm::Type* funcResultType;
+ llvm::Type* expectedResultType;
if (function->isPrefunction){
AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(pass->man->getPassById(PassId::AdhocPass));
adhocImplementation = adhocpass->determineForScope(entry);
- funcResultType = llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
+ expectedResultType = llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
} else {
- funcResultType = llvm->toLLVMType(ast->expandType(entry->__definitions[0]));
+ expectedResultType = llvm->toLLVMType(ast->expandType(entry->__definitions[0]));
}
- llvm::FunctionType *ft = llvm::FunctionType::get(funcResultType, types, false);
+ llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
- raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(function->__name + std::to_string(function.id()), ft));
+ raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, 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;
}
- if (sizeDom){
+ if (sizeLateContextDemand){
fargsI->setName("latecontext");
- lateContext.raw = fargsI;
+ contextCompiler.raw = fargsI;
}
const std::string&blockName = "entry";
+ llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
+
+ llvm::Value* result = entryCompilation->compile(blockName);
+ assert(result);
//SECTIONTAG types/convert function ret value
- llvm->builder.CreateRet(
- doAutomaticTypeConversion(
- entryCompilation->compile(blockName), funcResultType, llvm));
+ builder.CreateRet(doAutomaticTypeConversion(result, expectedResultType, llvm));
+
+ if (blockCurrent){
+ builder.SetInsertPoint(blockCurrent);
+ }
llvm->moveToGarbage(ft);
return raw;
}
llvm::Value*
-CompilePass::FunctionUnit::compileInline(std::vector<llvm::Value *> &&args, CompilePass::FunctionUnit* outer){
- CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
+FunctionUnit::compileInline(std::vector<llvm::Value *> &&args, 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){
+CodeScopeUnit*
+FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
- CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
+ 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(){
+CodeScopeUnit*
+FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
-CompilePass::CodeScopeUnit*
-CompilePass::FunctionUnit::getScopeUnit(ManagedScpPtr scope){
+CodeScopeUnit*
+FunctionUnit::getScopeUnit(ManagedScpPtr scope){
return getScopeUnit(&*scope);
}
-CompilePass::FunctionUnit*
+FunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function){
unsigned int id = function.id();
if (!functions.count(id)){
FunctionUnit* unit = new FunctionUnit(function, this);
functions.emplace(id, std::unique_ptr<FunctionUnit>(unit));
return unit;
}
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(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 ab199a4..17b4bdf 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,85 +1,101 @@
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
+#include <compilation/latecontextcompiler2.h>
#include "abstractpass.h"
#include "llvm/IR/Function.h"
-#include "compilation/latecontext.h"
+
+namespace xreate {
+ class AdhocScheme;
+ class ClaspLayer;
+ class ContextQuery;
+ class CallStatement;
+}
namespace xreate {
+class CompilePass;
-class AdhocScheme;
-class ClaspLayer;
-class ContextQuery;
+namespace compilation {
-class CompilePass : public AbstractPass<void> {
- friend class LateContext;
+class CodeScopeUnit;
+class FunctionUnit;
+
+
+struct Context{
+ FunctionUnit* function;
+ CodeScopeUnit* scope;
+ CompilePass* pass;
+};
+class CodeScopeUnit {
public:
- class CodeScopeUnit;
- class FunctionUnit{
- public:
- FunctionUnit(ManagedFnPtr f, CompilePass* 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;
-
- FunctionUnit* findFunctionUnit(const std::string f);
- };
-
- struct Context{
- FunctionUnit* function;
- CodeScopeUnit* scope;
- CompilePass* pass;
- };
+ 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;
+
+ CallStatement* findFunction(const std::string& callee);
+};
+
+class FunctionUnit{
+public:
+ FunctionUnit(ManagedFnPtr f, CompilePass* p)
+ : function(f), pass(p), contextCompiler(this, p) {}
+
+ llvm::Value* compileInline(std::vector<llvm::Value*>&& args, 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
+
+private:
+ CompilePass* pass;
+ std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
+
+public:
+ LateContextCompiler2 contextCompiler;
+};
+
+} // end of namespace `xreate::compilation`
+
+class CompilePass : public AbstractPass<void> {
+ friend class LateContextCompiler;
+ friend class LateContextCompiler2;
+ friend class compilation::CodeScopeUnit;
+ friend class compilation::FunctionUnit;
+
+public:
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
- FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
+ compilation::FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
void run() override;
llvm::Function* getEntryFunction();
static void prepareQueries(ClaspLayer* clasp);
private:
- std::map<unsigned int, std::unique_ptr<FunctionUnit>> functions;
+ std::map<unsigned int, std::unique_ptr<compilation::FunctionUnit>> functions;
llvm::Function* entry = 0;
ContextQuery* queryContext;
};
}
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/loggerpass.cpp b/cpp/src/pass/loggerpass.cpp
index b6fe477..ce8e552 100644
--- a/cpp/src/pass/loggerpass.cpp
+++ b/cpp/src/pass/loggerpass.cpp
@@ -1,106 +1,106 @@
/*
* logging.cpp
*
* Created on: Jun 23, 2015
* Author: pgess
*/
#include <pass/loggerpass.h>
#include "compilation/instr-containers.h"
#include "utils.h"
using namespace std;
using namespace llvm;
namespace xreate {
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
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* func = compiler->getFunctionUnit(context.function);
- CompilePass::CodeScopeUnit* scope = func->getScopeUnit(context.scope);
+ compilation::FunctionUnit* func = compiler->getFunctionUnit(context.function);
+ compilation::CodeScopeUnit* scope = func->getScopeUnit(context.scope);
- CompilePass::Context compilationContext{func, scope, compiler};
+ compilation::Context compilationContext{func, scope, compiler};
inject(v, compilationContext);
}
}
return AbstractPass<void>::process(expression, context, varDecl);
}
-void LoggerPass::inject(const Symbol& symbol, const CompilePass::Context& context){
+void LoggerPass::inject(const Symbol& symbol, const compilation::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
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);
}
}
LoggerPass::LoggerPass(PassManager* manager)
: AbstractPass<void>(manager)
{
initOutput();
init(man->clasp);
}
void
LoggerPass::initDependencies(CompilePass* pass){
compiler = pass;
}
} /* namespace xreate */
diff --git a/cpp/src/pass/loggerpass.h b/cpp/src/pass/loggerpass.h
index bfa3d0b..2c15b70 100644
--- a/cpp/src/pass/loggerpass.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 LoggerPass:public AbstractPass<void>, public IQuery {
public:
- void inject(const Symbol& symbol, const CompilePass::Context& context);
+ void inject(const Symbol& symbol, const compilation::Context& context);
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 87d8b8d..5f2dac3 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager.cpp
@@ -1,102 +1,112 @@
#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 <list>
+#include <stdio.h>
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);
+ return prepareForCode(&scanner);
}
PassManager*
-PassManager::prepareForCode(Scanner& scanner){
- Parser parser(&scanner);
+PassManager::prepareForCode(FILE* code){
+ Scanner scanner(code);
+ return prepareForCode(&scanner);
+}
+
+PassManager*
+PassManager::prepareForCode(Scanner* code){
+ Parser parser(code);
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);
//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, const PassId& id, AbstractPassBase* parent)
{
__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:
LoggerPass* logger = new LoggerPass(this);
logger->initDependencies(compiler);
logger->run();
llvm->print();
llvm->initJit();
return llvm->getFunctionPointer(compiler->getEntryFunction());
}
void PassManager::runWithoutCompilation(){
+ if (flagIsProcessed) return;
+
std::list<AbstractPassBase*> passes{nullptr};
while (passes.size()){
AbstractPassBase* parent = passes.front();
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->run();
+ flagIsProcessed = true;
}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index 389487f..86de4f3 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,45 +1,53 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
-#include "Scanner.h"
#include <string>
#include <map>
+//stdio external
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+
+class Scanner;
+
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 runWithoutCompilation();
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);
+ static PassManager* prepareForCode(FILE* code);
ClaspLayer* clasp;
LLVMLayer* llvm;
AST* root;
private:
//typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
//FILTERS_STORAGE __filters;
std::map<PassId, AbstractPassBase*> __passes;
std::multimap<AbstractPassBase*, AbstractPassBase*> __passDependencies;
+ bool flagIsProcessed = false;
+
+ static PassManager* prepareForCode(Scanner* code);
}; }
#endif
diff --git a/cpp/src/query/context.cpp b/cpp/src/query/context.cpp
index 0f4399b..732ca16 100644
--- a/cpp/src/query/context.cpp
+++ b/cpp/src/query/context.cpp
@@ -1,129 +1,167 @@
/*
* adhoc.cpp
*
* Created on: Dec 1, 2015
* Author: pgess
*/
#include <query/context.h>
#include <boost/range/iterator_range_core.hpp>
+#include <boost/iterator/transform_iterator.hpp>
using namespace std;
namespace xreate {
-std::list<Expression>
-ContextQuery::getContext(const ScopePacked& scopeId){
- std::list<Expression> result;
+ContextQuery::ContextQuery()
+ : domainEmpty(vector<Expression>()) {}
- for (auto i: boost::make_iterator_range(__modelContext.equal_range(scopeId))){
- result.push_back(i.second);
+const ContextDomain&
+ContextQuery::getContext(const ScopePacked& scopeId){
+ if (!__modelContext.count(scopeId)){
+ return domainEmpty;
}
- for (auto i: boost::make_iterator_range(__modelForcedContext.equal_range(scopeId))){
- result.push_back(i.second);
- }
+ return __modelContext.at(scopeId);
+}
- return result;
+const ContextDomain&
+ContextQuery::getContext(CodeScope* const scope){
+ return getContext(clasp->pack(scope));
}
void
ContextQuery::forceContext(const ScopePacked& scopeId, std::list<Expression> context){
- // TODO remove forced context only of the same class, possibly
-
+ // TODO remove forced context of the same class/type only, possibly
//remove any previous forced context for this scopeId
- __modelForcedContext.erase(scopeId);
+ //__modelForcedContext.erase(scopeId);
+ //TASK restore forceContext
+ //std::multimap<ScopePacked, Expression> __modelForcedContext;
+ /*
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){
+ this->clasp = clasp;
+ ClaspLayer::ModelFragment query = clasp->query(atomEarlyBinding);
+
+ //static context
+ if (query){
+ map<ScopePacked, vector<Expression>> dictContext;
+
+ for (auto i = query->first; i!=query->second; ++i){
ScopePacked idScope;
Expression context;
tie(idScope, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
- __modelContext.emplace(idScope, context);
+ dictContext[idScope].push_back(context);
}
- }
- const std::string& atomLateBinding = Config::get("clasp.bindings.scope_weak");
- model = clasp->query(atomEarlyBinding);
+ for (map<ScopePacked, vector<Expression>>::value_type& entry: dictContext){
+ __modelContext.insert(move(entry));
+ }
+ }
- 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);
+ //static decisions
+ query = clasp->query(Config::get("clasp.bindings.scope_decision"));
+ if (query){
+ for (auto i = query->first; i!=query->second; ++i){
+ ScopePacked scopeId;
+ string function;
+ Expression specialization;
+ tie(scopeId, function, specialization) = ClaspLayer::parse<ScopePacked, string, Expression>(i->second);
+ ScopeContextDecisions& scope = __modelStaticDecisions[scopeId];
+ assert(scope.emplace(function, specialization).second && "Possibly more than one decision");
}
+ }
- for(auto& entry: modelLateContext){
- __modelFunctionContext.emplace(entry.first, move(entry.second));
+ //Fetch function specialization domains
+ std::multimap<string, Expression> modelDomains;
+ const list<ManagedFnPtr>& functions = clasp->ast->getAllFunctions();
+ for (auto f: functions){
+ if (f->guardContext.isValid()){
+ modelDomains.emplace(f->getName(), f->guardContext);
}
}
+
+ auto adapter = [](const std::pair<const string&,const Expression>& p){ return p.second; };
+
+ auto iBegin = modelDomains.begin();
+ while (iBegin!=modelDomains.end()){
+ string function = iBegin->first;
+ auto iEnd = modelDomains.upper_bound(function);
+ auto iBeginAdapted = boost::make_transform_iterator(iBegin,adapter);
+ auto iEndAdapted = boost::make_transform_iterator(iEnd,adapter);
+ ContextDomain dom(iBeginAdapted, iEndAdapted);
+ __modelFunctionDomain.emplace(function, move(dom));
+ iBegin = iEnd;
+ }
+
+ prepareDemandModel();
}
const ContextDomain&
ContextQuery::getFunctionDomain(const std::string& name) const {
- static ContextDomain domainNULL({});
-
- if (__modelFunctionContext.count(name)){
- return __modelFunctionContext.at(name);
+ if (__modelFunctionDomain.count(name)){
+ return __modelFunctionDomain.at(name);
}
- return domainNULL;
+ return domainEmpty;
}
-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++);
+const FunctionContextDemand&
+ContextQuery::getFunctionDemand(const std::string& name) const {
+ if (__modelFunctionDemand.count(name)){
+ return __modelFunctionDemand.at(name);
}
-}
-size_t
-ContextDomain::size() const{
- return PARENT::size();
+ return decisionsEmpty;
}
+const ScopeContextDecisions&
+ContextQuery::getStaticDecisions(const ScopePacked& scopeId){
+ if (__modelStaticDecisions.count(scopeId)){
+ return __modelStaticDecisions[scopeId];
+ }
-ContextDomain::const_iterator
-ContextDomain::begin() const {
- return begin();
-}
-
-ContextDomain::const_iterator
-ContextDomain::end() const {
- return end();
+ return contextDecisionsEmpty;
}
-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);
+void
+ContextQuery::prepareDemandModel(){
+ const std::string& atomFunctionDemand = Config::get("clasp.bindings.function_demand");
+
+ ClaspLayer::ModelFragment query = clasp->query(atomFunctionDemand);
+ if (query)
+ for (auto i = query->first; i!=query->second; ++i){
+ string function;
+ string decision;
+ tie(function, decision) = ClaspLayer::parse<string, string>(i->second);
+
+ FunctionContextDemand& decisions = __modelFunctionDemand[function];
+ decisions.left.insert(make_pair(decisions.size(), decision));
}
-
- return boost::none;
}
-const Expression&
-ContextDomain::get(size_t id) const{
- return at(id);
-}
+// const std::string& atomLateBinding = Config::get("clasp.bindings.function_uncertain");
+// query = clasp->query(atomLateBinding);
+//
+// std::map<std::string, std::vector<Expression>> dictFunctionDomain;
+// if (query){
+// for (auto i = query->first; i!=query->second; ++i){
+// string nameFunction;
+// Expression context;
+// tie(nameFunction, context) = ClaspLayer::parse<ScopePacked, Expression>(i->second);
+// dictFunctionDomain.at(nameFunction).push_back(context);
+// }
+//
+// for(auto& entry: dictFunctionDomain){
+// __modelFunctionDomain.emplace(entry.first, move(entry.second));
+// }
+// }
+
} /* namespace xreate */
diff --git a/cpp/src/query/context.h b/cpp/src/query/context.h
index 6da9f9d..7117ac0 100644
--- a/cpp/src/query/context.h
+++ b/cpp/src/query/context.h
@@ -1,81 +1,89 @@
/*
* 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 "serialization.h"
#include <unordered_map>
+
+#include <boost/bimap.hpp>
namespace xreate {
-class ContextDomain: private std::vector<Expression>{
- typedef std::vector<Expression> PARENT;
+typedef ExpressionSerialization<RequirementIntegralCode>::Serializer ContextDomain;
+typedef boost::bimap<size_t, std::string> FunctionContextDemand;
+typedef std::map<std::string, Expression> ScopeContextDecisions;
+class ContextQuery: public IQuery {
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;
-
+ //AdhocQuery();
+ const ContextDomain& getContext(const ScopePacked& scopeId);
+ const ContextDomain& getContext(CodeScope* const scope);
+ void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
+ const ContextDomain& getFunctionDomain(const std::string& name) const;
+ const FunctionContextDemand& getFunctionDemand(const std::string& name) const;
+ const ScopeContextDecisions& getStaticDecisions(const ScopePacked& scopeId);
+ virtual void init(ClaspLayer* clasp);
+ ContextQuery();
+ virtual ~ContextQuery(){};
private:
- ContextDomain(const ContextDomain&)=delete;
+ ClaspLayer* clasp;
+ std::map<ScopePacked, ContextDomain> __modelContext;
+ std::map<std::string, ContextDomain> __modelFunctionDomain;
+ std::map<std::string, FunctionContextDemand> __modelFunctionDemand;
+ std::map<ScopePacked, ScopeContextDecisions> __modelStaticDecisions;
+
+ const ContextDomain domainEmpty;
+ const FunctionContextDemand decisionsEmpty;
+ const ScopeContextDecisions contextDecisionsEmpty;
- std::map<PackedExpression, size_t> scheme;
- ExpressionSerializer serializer;
+ void prepareDemandModel();
};
+} /* namespace xreate */
+
+/*
template <typename ATTACHMENTS>
class ContextAttachments: private std::unordered_map<size_t, ATTACHMENTS> {
typedef std::unordered_map<size_t, ATTACHMENTS> PARENT;
public:
+ ContextAttachments(ContextAttachments&& other)
+ : PARENT(std::move(other)), domain(std::move(other.domain)) {}
+
+ ContextAttachments(std::vector<Expression>&& expressions, std::vector<ATTACHMENTS>&& attachments)
+ : domain(move(expressions))
+ {
+ size_t size = domain.size();
+ for (size_t i=0; i<size; ++i){
+ PARENT::emplace(i, std::move(attachments[i]));
+ }
+ }
+
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/serialization.h b/cpp/src/serialization.h
new file mode 100644
index 0000000..08425af
--- /dev/null
+++ b/cpp/src/serialization.h
@@ -0,0 +1,30 @@
+/*
+ * serialization.h
+ *
+ * Created on: 13 февр. 2016
+ * Author: pgess
+ */
+
+#ifndef SRC_SERIALIZATION_SERIALIZATION_H_
+#define SRC_SERIALIZATION_SERIALIZATION_H_
+
+#include "serialization/expressionserializer.h"
+
+namespace xreate {
+struct RequirementIntegralCode{};
+
+template<class Requirements=void>
+struct ExpressionSerialization {
+ typedef PackedExpression Code;
+ typedef ExpressionSerializer Serializer;
+};
+
+template<>
+struct ExpressionSerialization<RequirementIntegralCode>{
+ typedef size_t Code;
+ typedef ExpressionSerializerIntegral Serializer;
+};
+}
+
+
+#endif /* SRC_SERIALIZATION_SERIALIZATION_H_ */
diff --git a/cpp/src/expressionserializer.cpp b/cpp/src/serialization/expressionserializer.cpp
similarity index 76%
rename from cpp/src/expressionserializer.cpp
rename to cpp/src/serialization/expressionserializer.cpp
index 34d67c2..af7e8f1 100644
--- a/cpp/src/expressionserializer.cpp
+++ b/cpp/src/serialization/expressionserializer.cpp
@@ -1,231 +1,287 @@
/*
* expressionserializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
-#include <expressionserializer.h>
+#include "serialization/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;
+ //boost::bimap<Index, multiset_of<size_t>> __registry;
+ struct {
+ map<Index,size_t> left;
+ } __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)){
+ 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){
+ if (e.isValid())
strategy->registerExpression(e, 0);
}
PackedExpression
-ExpressionSerializer::pack(const Expression& e){
- OptionalPackedExpression result;
+ExpressionSerializer::getId(const Expression& e){
+ OptionalPackedExpression result(move(PackedExpression()));
strategy->pack(e, 0, result);
assert(result);
return move(*result);
}
OptionalPackedExpression
-ExpressionSerializer::packOptional(const Expression& e) const{
- OptionalPackedExpression result;
+ExpressionSerializer::getIdOptional(const Expression& e) const{
+ OptionalPackedExpression result(move(PackedExpression()));
strategy->pack(e, 0, result);
return result;
}
+ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector<Expression>&& expressions)
+ : std::vector<Expression>(move(expressions)), serializer(*this){
+
+ size_t id =0;
+ for (const Expression& e: expressions){
+ __registry.emplace(serializer.getId(e), id++);
+ }
+}
+
+size_t
+ExpressionSerializerIntegral::size() const{
+ return PARENT::size();
+}
+
+size_t
+ExpressionSerializerIntegral::count(const Expression& e) const {
+ return (getIdOptional(e)? 1: 0);
+}
+
+ExpressionSerializerIntegral::const_iterator
+ExpressionSerializerIntegral::begin() const {
+ return PARENT::begin();
+}
+
+ExpressionSerializerIntegral::const_iterator
+ExpressionSerializerIntegral::end() const {
+ return PARENT::end();
+}
+
+size_t
+ExpressionSerializerIntegral::getId(const Expression& e) const{
+ const auto& exprPacked = serializer.getIdOptional(e);
+ assert(exprPacked);
+
+ return __registry.at(*exprPacked);
+}
+
+boost::optional<size_t>
+ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{
+ const auto& exprPacked = serializer.getIdOptional(e);
+ if (!exprPacked){
+ return boost::none;
+ }
+
+ return __registry.at(*exprPacked);
+}
+
+const Expression&
+ExpressionSerializerIntegral::get(size_t id) const{
+ return at(id);
+}
+
+
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/serialization/expressionserializer.h b/cpp/src/serialization/expressionserializer.h
new file mode 100644
index 0000000..b4b2354
--- /dev/null
+++ b/cpp/src/serialization/expressionserializer.h
@@ -0,0 +1,100 @@
+/*
+ * 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:
+ template<class Container>
+ ExpressionSerializer(const Container& source): ExpressionSerializer(){
+ for (const Expression& e: source) {
+ registerExpression(e);
+ }
+ }
+
+ template<class Container, class Transformer>
+ ExpressionSerializer(const Container& source, Transformer op): ExpressionSerializer(){
+ for (const typename Container::value_type& e: source) {
+ registerExpression(op(e));
+ }
+ }
+
+ ExpressionSerializer(ExpressionSerializer&& other)
+ : strategy(other.strategy) {other.strategy = 0; }
+
+ virtual ~ExpressionSerializer();
+
+ PackedExpression getId(const Expression& e);
+ OptionalPackedExpression getIdOptional(const Expression& e) const;
+
+private:
+ ExpressionSerializerPrivate* strategy;
+
+ void registerExpression(const Expression&e);
+ ExpressionSerializer();
+};
+
+class ExpressionSerializerIntegral: private std::vector<Expression>{
+ typedef std::vector<Expression> PARENT;
+
+public:
+ ExpressionSerializerIntegral(const std::vector<Expression>&& expressions);
+ template<class Iterator>
+ ExpressionSerializerIntegral(Iterator first, Iterator last)
+ : ExpressionSerializerIntegral(std::vector<Expression>(first, last)){}
+
+ ExpressionSerializerIntegral(ExpressionSerializerIntegral&& other)
+ : PARENT(std::move(other)), __registry(std::move(other.__registry)), serializer(std::move(other.serializer)){}
+ size_t getId(const Expression& e) const;
+ boost::optional<size_t> getIdOptional(const Expression& e) const;
+ const Expression& get(size_t id) const;
+ size_t size() const;
+ size_t count(const Expression& e) const;
+ ExpressionSerializerIntegral::const_iterator begin() const;
+ ExpressionSerializerIntegral::const_iterator end() const;
+
+private:
+ ExpressionSerializerIntegral(const ExpressionSerializerIntegral&)=delete;
+
+ std::map<PackedExpression, size_t> __registry;
+ ExpressionSerializer serializer;
+};
+
+
+
+} /* namespace xreate */
+
+#endif /* SRC_EXPRESSIONSERIALIZER_H_ */
diff --git a/cpp/src/serialization/expressionserializer2.cpp b/cpp/src/serialization/expressionserializer2.cpp
new file mode 100644
index 0000000..5c63641
--- /dev/null
+++ b/cpp/src/serialization/expressionserializer2.cpp
@@ -0,0 +1,98 @@
+/*
+ * ExpressionSerializer2.cpp
+ *
+ * Created on: 9 февр. 2016
+ * Author: pgess
+ */
+
+#include "expressionserializer2.h"
+
+using namespace std;
+
+namespace xreate {
+
+typedef size_t ElementId;
+struct Element{
+ string name;
+ unsigned char degree;
+ ElementId terminal = 0;
+ std::list<ElementId> childs;
+
+ bool operator< (const Element& other) {
+ int cmp = name.compare(other.name);
+ if (cmp !=0) return (cmp < 0);
+ return (degree < other.degree);
+ }
+
+ bool operator== (const Element& other) {
+ int cmp = name.compare(other.name);
+ if (cmp != 0) return false;
+ return degree == other.degree;
+ }
+
+ Element(string nameElement, unsigned int degreeElement)
+ : name(nameElement), degree(degreeElement) {}
+};
+
+const Element End{"", 0};
+
+class ExpressionSerializerStrategyB {
+ vector<Element> __registry;
+
+ ElementId push(const Element& e, ElementId rootId){
+ typedef list<ElementId>::iterator ElementIt;
+
+ list<ElementId>& elements = __registry[rootId].childs;
+ list<ElementId>::iterator pos = std::__lower_bound(elements.begin(), elements.end(), e,
+ [this](const ElementIt& testIt, const Element& value){return __registry[*testIt] < value;});
+
+ if (!(__registry[*pos] == e)) {
+ __registry.push_back(e);
+ ElementId result = __registry.size()-1;
+ elements.insert(pos, result);
+ return result;
+ }
+
+ return *pos;
+ }
+
+ ElementId registerExpression(const Expression& e, ElementId rootId) {
+ switch(e.op){
+ case Operator::NONE: {
+ switch (e.__state) {
+ case Expression::STRING:
+ case Expression::IDENT: {
+ const string& name = e.getValueString();
+ Element element(name, 0);
+ ElementId rootId = push(element, rootId);
+ return rootId;
+ }
+
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+
+ case Operator::CALL: {
+ const string& name = e.getValueString();
+ Element element(name, e.operands.size());
+ ElementId rootId = push(element, rootId);
+
+ for (const Expression& op: e.operands){
+ Element element(op.getValueString(), op.operands.size());
+ rootId = push(element, rootId);
+ }
+
+ return rootId;
+ }
+
+ default: break;
+ }
+
+ assert(false && "Expression too complicate for serialization");
+ }
+};
+
+} /* namespace xreate */
diff --git a/cpp/src/serialization/expressionserializer2.h b/cpp/src/serialization/expressionserializer2.h
new file mode 100644
index 0000000..3b29756
--- /dev/null
+++ b/cpp/src/serialization/expressionserializer2.h
@@ -0,0 +1,25 @@
+/*
+ * ExpressionSerializer2.h
+ *
+ * Created on: 9 февр. 2016
+ * Author: pgess
+ */
+
+#ifndef EXPRESSIONSERIALIZER2_H_
+#define EXPRESSIONSERIALIZER2_H_
+
+#include <ast.h>
+
+namespace xreate {
+
+class ExpressionSerializer2 {
+public:
+ ExpressionSerializer2();
+ virtual ~ExpressionSerializer2();
+
+ void registerExpression(const Expression& e);
+};
+
+} /* namespace xreate */
+
+#endif /* EXPRESSIONSERIALIZER2_H_ */
diff --git a/cpp/tests/ExpressionSerializer2_test.cpp b/cpp/tests/ExpressionSerializer2_test.cpp
new file mode 100644
index 0000000..9170de7
--- /dev/null
+++ b/cpp/tests/ExpressionSerializer2_test.cpp
@@ -0,0 +1,12 @@
+/*
+ * ExpressionSerializer2_test.cpp
+ *
+ * Created on: 9 февр. 2016
+ * Author: pgess
+ */
+
+#include "serialization/expressionserializer2.h"
+
+namespace xreate {
+
+} /* namespace xreate */
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index c305e3e..97e4087 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,5 +1,62 @@
+#include "passmanager.h"
#include "gtest/gtest.h"
+using namespace xreate;
//TEST FunctionUnit::compileInline
TEST(Compilation, DISABLED_functionInline1){
}
+
+//DEBT implement no pkgconfig ways to link libs
+TEST(Compilation, Sequence1){
+ PassManager* man = PassManager::prepareForCode(
+ "interface(extern-c){\n"
+ " libFake = library:: pkgconfig(\"libxml-2.0\").\n"
+ " \n"
+ " include {\n"
+ " libFake = [\"stdio.h\", \"stdlib.h\"]\n"
+ " }.\n"
+ "}"
+
+ "main = function:: int; entry {\n"
+ " sequence ["
+ " printf(\"FIRST-\"),\n"
+ " printf(\">SECOND\")\n"
+ " ]"
+ "}"
+ );
+
+ int (*main)() = (int (*)()) man->run();
+
+ testing::internal::CaptureStdout();
+ main();
+ std::string output = testing::internal::GetCapturedStdout();
+
+ ASSERT_STREQ("FIRST->SECOND", output.c_str());
+}
+
+TEST(Compilation, full_IFStatementWithVariantType){
+ PassManager* man = PassManager::prepareForCode(
+ "COLORS = type variant (RED, BLUE, GREEN).\n"
+ "\n"
+ " main = function(x::int):: int; entry {\n"
+ " color = if (x == 0 )::COLORS {RED} else {BLUE}.\n"
+ " if (color == BLUE)::int {1} else {0}\n"
+ " }"
+ );
+
+ int (*main)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(0, main(0));
+ ASSERT_EQ(1, main(1));
+}
+
+// "main = function:: int; entry {\n"
+// " context:: expectNoErrors. "
+// " buf1 = \"aaaaa\"::string.\n"
+// " buf2 = \"aaaaa\"::string.\n"
+// " sequence ["
+// " sprintf(buf1, \"%d\", exec(\"bazaar --version\")),"
+// " sprintf(buf2, \"%d\", exec(\"svn --version\")),"
+// " printf(buf1),\n"
+// " printf(buf2)\n"
+// "]"
+// "}"
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 611ccfe..e2c3e76 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,54 +1,54 @@
/*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess
*/
-#include "gtest/gtest.h"
+
#include "passmanager.h"
-#include "Parser.h"
#include "query/containers.h"
+#include "Parser.h"
+#include "gtest/gtest.h"
using namespace std;
using namespace xreate;
using namespace containers;
TEST(Containers, ContanierLinkedList1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
Symbol symb_chilrenRaw = body->findSymbol("childrenRaw");
containers::ImplementationLinkedList iLL(symb_chilrenRaw);
ASSERT_EQ(true, static_cast<bool>(iLL));
ASSERT_EQ("next", iLL.fieldPointer);
Implementation impl = Implementation::create(symb_chilrenRaw);
ASSERT_NO_FATAL_FAILURE(impl.extract<ON_THE_FLY>());
ImplementationRec<ON_THE_FLY> recOnthefly = impl.extract<ON_THE_FLY>();
ASSERT_EQ(symb_chilrenRaw, recOnthefly.source);
}
TEST(Containers, Implementation_LinkedListFull){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
- Scanner scanner(input);
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(scanner));
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
ASSERT_EQ(16, answer);
fclose(input);
}
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
index 485a7c1..77f2d8a 100644
--- a/cpp/tests/context.cpp
+++ b/cpp/tests/context.cpp
@@ -1,198 +1,267 @@
/*
* frame-context.cpp
*
* Created on: Dec 3, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "query/context.h"
#include "gtest/gtest.h"
+#include <iostream>
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));
+ const ContextDomain& 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));
}
+
+
+
+TEST(Context, full_LateContext){
+ PassManager* man = PassManager::prepareForCode(
+ "import raw (\"core/control-context.lp\")\n"
+
+ " convert = function(length:: num)::num{\n"
+ " 0\n"
+ " }\n"
+
+ "case context:: milli {\n"
+ " convert = function(length:: num)::num{\n"
+ " 1000 * length\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "case context:: centi {\n"
+ " convert = function(length:: num)::num{\n"
+ " 100 * length\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "calculate = function(length:: num)::num {\n"
+ " convert(length)\n"
+ "}\n"
+ "\n"
+ "main = function(com:: num):: num; entry {\n"
+ " switch (com):: num \n"
+ " case 0 {\n"
+ " context:: milli.\n"
+ " calculate(1)\n"
+ " }\n"
+ "\n"
+ " case default{\n"
+ " context:: centi. \n"
+ " calculate(1)\n"
+ " }\n"
+ "}");
+
+ man->runWithoutCompilation();
+ ContextQuery* queryContext = reinterpret_cast<ContextQuery*>(man->clasp->getQuery(QueryId::ContextQuery));
+ Expression exprSwitch = man->root->findFunction("main")->__entry->__body;
+ CodeScope* blockDefault = man->root->findFunction("main")->__entry->__body.operands[1].blocks.front();
+ ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
+ const ContextDomain& domDefault = queryContext->getContext(blockDefaultId);
+ ASSERT_EQ(1, domDefault.count(Expression(Atom<Identifier_t>("centi"))));
+
+ std::list<ManagedFnPtr> variants = man->root->getFunctionVariants("convert");
+ for (ManagedFnPtr f: variants){
+ const Expression guard = f->guardContext;
+ bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid());
+ ASSERT_TRUE(result);
+ }
+
+ const FunctionContextDemand& demMain = queryContext->getFunctionDemand("main");
+ ASSERT_EQ(0, demMain.size());
+
+ const FunctionContextDemand& demCalculate = queryContext->getFunctionDemand("calculate");
+ ASSERT_EQ(1, demCalculate.size());
+ ASSERT_EQ(1, demCalculate.right.count("convert"));
+
+ int (*entry)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(1000, entry(0));
+ ASSERT_EQ(100, entry(1));
+}
+
+
diff --git a/cpp/tests/expressions.cpp b/cpp/tests/expressions.cpp
deleted file mode 100644
index 6b6e732..0000000
--- a/cpp/tests/expressions.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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/pass-Logger.cpp b/cpp/tests/pass-Logger.cpp
index a1da4c7..2999b73 100644
--- a/cpp/tests/pass-Logger.cpp
+++ b/cpp/tests/pass-Logger.cpp
@@ -1,87 +1,85 @@
/*
* 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"
using namespace std;
using namespace xreate;
TEST(LoggerPass, simpleInjection){
PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");
man->runWithoutCompilation();
CompilePass* compiler = new CompilePass(man);
compiler->run();
- CompilePass::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("test"));
+ compilation::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("test"));
ASSERT_NE(fTest, nullptr);
- CompilePass::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
+ compilation::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, compiler};
+ compilation::Context params{fTest, scopeUnitTest, compiler};
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(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();
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(LoggerPass, simpleInjection3){
FILE* input = fopen("scripts/cases/log.xreate","r");
- assert(input != nullptr);
+ assert(input);
- Scanner scanner(input);
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(scanner));
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
fclose(input);
}
diff --git a/cpp/tests/sprint1-installation.cpp b/cpp/tests/sprint1-installation.cpp
new file mode 100644
index 0000000..b4dda10
--- /dev/null
+++ b/cpp/tests/sprint1-installation.cpp
@@ -0,0 +1,22 @@
+/*
+ * sprint1-installation.cpp
+ *
+ * Created on: 26 Feb 2016
+ * Author: pgess
+ */
+
+#include "passmanager.h"
+#include "gtest/gtest.h"
+#include <stdio.h>
+using namespace std;
+using namespace xreate;
+
+//TODO replace string identifiers with Atoms in order to hold position, etc
+TEST(Sprint1, test1){
+ const string filenameSource("scripts/testspass/sprint1-Installation1.xreate");
+ FILE* fileSource;
+ ASSERT_TRUE(fileSource = fopen(filenameSource.c_str(), "rb"));
+
+ PassManager* man = PassManager::prepareForCode(fileSource);
+ man->run();
+}
diff --git a/cpp/tests/testExpressionSerializer.cpp b/cpp/tests/testExpressionSerializer.cpp
index 9fd30f3..c5dc128 100644
--- a/cpp/tests/testExpressionSerializer.cpp
+++ b/cpp/tests/testExpressionSerializer.cpp
@@ -1,50 +1,65 @@
/*
* testExpressionSerializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
-#include "expressionserializer.h"
+#include "serialization/expressionserializer.h"
+#include "serialization.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);
+ ExpressionSerializer serializer(vector<Expression>{a, b});
- PackedExpression packA = serializer.pack(a);
- PackedExpression packB = serializer.pack(b);
- PackedExpression packA2 = serializer.pack(a);
+ PackedExpression packA = serializer.getId(a);
+ PackedExpression packB = serializer.getId(b);
+ PackedExpression packA2 = serializer.getId(a);
ASSERT_EQ(packA, packA2);
ASSERT_NE(packA, packB);
}
+TEST(ExpressionSerializer, serialize2){
+ Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))});
+ Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))});
+ Expression c(Atom<Identifier_t>("c"));
+
+ typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Serializer;
+ Serializer serializer(vector<Expression>{a, b});
+
+ ASSERT_EQ(2, serializer.size());
+ ASSERT_EQ(1, serializer.count(a));
+ ASSERT_EQ(1, serializer.count(b));
+ ASSERT_EQ(0, serializer.count(c));
+ Serializer serializer2(move(serializer));
+ ASSERT_EQ(1, serializer2.count(a));
+}
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 9801984..5815c3b 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,149 +1,167 @@
/*
* 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(Types, full_VariantType_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());
+}
+
+
//TEST string type
diff --git a/cpp/tests/xml.cpp b/cpp/tests/xml.cpp
index cb62100..653f60e 100644
--- a/cpp/tests/xml.cpp
+++ b/cpp/tests/xml.cpp
@@ -1,31 +1,29 @@
#include "passmanager.h"
-#include "Scanner.h"
-
#include "gtest/gtest.h"
+#include <stdio.h>
using namespace xreate;
TEST(Xml, Main){
- FILE* input = fopen("scripts/xml/input.xreate", "r");
- assert(input != nullptr);
+ FILE* input = fopen("scripts/testspass/xml-test1.xreate", "r");
+ assert(input);
- Scanner scanner(input);
- PassManager* program = PassManager::prepareForCode(scanner);
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
}
TEST(Xml, DISABLED_AliasTuple){
}
TEST(Xml, DISABLED_FoldProtoEnhanced){
}
TEST(Xml, DISABLED_TransfucPropagation){
}
diff --git a/scripts/containers/Containers_Implementation_LinkedList1.xreate b/scripts/containers/Containers_Implementation_LinkedList1.xreate
new file mode 120000
index 0000000..25bdd31
--- /dev/null
+++ b/scripts/containers/Containers_Implementation_LinkedList1.xreate
@@ -0,0 +1 @@
+/private/prg/code/xreate/scripts/testspass/Containers_Implementation_LinkedList1.xreate
\ No newline at end of file
diff --git a/scripts/cases/containers.xreate b/scripts/containers/containers.xreate
similarity index 100%
rename from scripts/cases/containers.xreate
rename to scripts/containers/containers.xreate
diff --git a/scripts/environment-tests/dependencies.lp b/scripts/environment-tests/dependencies.lp
deleted file mode 120000
index 7db9889..0000000
--- a/scripts/environment-tests/dependencies.lp
+++ /dev/null
@@ -1 +0,0 @@
-/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
deleted file mode 100644
index 1fc241b..0000000
--- a/scripts/environment-tests/sequence
+++ /dev/null
@@ -1,62 +0,0 @@
-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-early_late_binding.lp b/scripts/environment-tests/tests-early_late_binding.lp
deleted file mode 100644
index a59a8fe..0000000
--- a/scripts/environment-tests/tests-early_late_binding.lp
+++ /dev/null
@@ -1,21 +0,0 @@
-%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/tests-context.lp b/scripts/metatests/(invalid)tests-context.lp
similarity index 100%
rename from scripts/environment-tests/tests-context.lp
rename to scripts/metatests/(invalid)tests-context.lp
diff --git a/scripts/metatests/context-latecontext-ContextLoopResolution-direct.lp b/scripts/metatests/context-latecontext-ContextLoopResolution-direct.lp
new file mode 100644
index 0000000..8d1c8b6
--- /dev/null
+++ b/scripts/metatests/context-latecontext-ContextLoopResolution-direct.lp
@@ -0,0 +1 @@
+
diff --git a/core/control-context.lp b/scripts/metatests/control-context-demandContext.lp
similarity index 56%
copy from core/control-context.lp
copy to scripts/metatests/control-context-demandContext.lp
index 1c27c0f..494ab0f 100644
--- a/core/control-context.lp
+++ b/scripts/metatests/control-context-demandContext.lp
@@ -1,27 +1,20 @@
-%TODO context-dependent function specialization implemenetation(inline/...)
-
% context propagation
+bind_scope_demand(Scope, FnCallee):- cfa_call(Scope, FnCallee), cfa_function_specializations(FnCallee, Context), not bind_scope(Scope, Context).
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_demand(Scope, Context):- bind_function_demand(FnChild, Context), cfa_call(Scope, FnChild), not bind_scope(Scope, Context).
+
+bind_function_demand(Fn, Context):- bind_scope_demand(Scope, Context), cfa_parent(Scope, 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)).
+%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).
-
-
+%scope_function(Scope, Fn) :- cfa_parent(Scope, scope(ScopeParent)), scope_function(ScopeParent, Fn).
\ No newline at end of file
diff --git a/scripts/metatests/tests-context-late_context.lp b/scripts/metatests/tests-context-late_context.lp
new file mode 100644
index 0000000..536cdd3
--- /dev/null
+++ b/scripts/metatests/tests-context-late_context.lp
@@ -0,0 +1,26 @@
+#include "control-context.lp".
+
+%body
+function(a;b;c;d).
+scope(0..4).
+cfa_parent(0, function(a)).
+cfa_parent(1, function(b)).
+cfa_parent(2, function(c)).
+cfa_parent(3, function(d)).
+cfa_parent(4, function(d)).
+
+cfa_call(0, c).
+cfa_call(1, c).
+cfa_call(2, d).
+
+bind_scope(0, a).
+bind_scope(1, b).
+
+cfa_function_specializations(d, a).
+cfa_function_specializations(d, b).
+
+#show bind_scope_decision/3.
+%#show bind_scope_demand/2.
+#show bind_function_demand/2.
+%#show cfa_call/2.
+%#show bind_function_demand/2.
\ No newline at end of file
diff --git a/scripts/environment-tests/control-context.lp b/scripts/sprint1_environment/control-context.lp
similarity index 100%
rename from scripts/environment-tests/control-context.lp
rename to scripts/sprint1_environment/control-context.lp
diff --git a/scripts/environment-tests/current b/scripts/sprint1_environment/current
similarity index 100%
rename from scripts/environment-tests/current
rename to scripts/sprint1_environment/current
diff --git a/core/dependencies.lp b/scripts/sprint1_environment/dependencies.lp
similarity index 100%
rename from core/dependencies.lp
rename to scripts/sprint1_environment/dependencies.lp
diff --git a/scripts/sprint1_environment/sprint1-Installation1.xreate b/scripts/sprint1_environment/sprint1-Installation1.xreate
new file mode 120000
index 0000000..31eab23
--- /dev/null
+++ b/scripts/sprint1_environment/sprint1-Installation1.xreate
@@ -0,0 +1 @@
+/private/prg/code/xreate/scripts/testspass/sprint1-Installation1.xreate
\ No newline at end of file
diff --git a/scripts/environment-tests/xreate-environment b/scripts/sprint1_environment/xreate-environment
similarity index 100%
rename from scripts/environment-tests/xreate-environment
rename to scripts/sprint1_environment/xreate-environment
diff --git a/scripts/testspass/log.xreate b/scripts/testspass/log.xreate
new file mode 100644
index 0000000..997edf1
--- /dev/null
+++ b/scripts/testspass/log.xreate
@@ -0,0 +1,64 @@
+/*
+
+ Log level:
+ Log entry(flat, hierarchical)
+
+*/
+
+
+
+
+ // EXTERN INCLUDES
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h", "string.h"]
+ }.
+}
+
+ // CONTAINERS
+interface(dfa) {
+ operator map:: (op(seqaccess)) -> impl(solid).
+ operator list_range:: ()->impl(on_the_fly).
+ operator list:: ()->impl(solid).
+ operator fold:: (op(seqaccess)).
+ operator index:: (op(randaccess)).
+ /* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
+}
+
+import raw("core/containers.lp").
+
+
+ // PROGRAM
+XmlNode = type alias {
+ tag:: string,
+ /* attrs:: [string],*/
+ content:: string
+}.
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+
+test= function():: num; entry {
+ filename = "project/documentation.fodt" :: string.
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+ childrenRaw = tree["children"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+ size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int):: int {
+
+// $log{
+// count +1:: warning, subsystem=xml
+// }
+
+
+ //log{warning, subsystem=xml, ..}
+ childName = child["name"]::string; logging.
+ count + strlen(childName):: int
+ }.
+
+ size
+}
+
+
diff --git a/scripts/testspass/sprint1-Installation1.xreate b/scripts/testspass/sprint1-Installation1.xreate
new file mode 100644
index 0000000..e02797f
--- /dev/null
+++ b/scripts/testspass/sprint1-Installation1.xreate
@@ -0,0 +1,100 @@
+import raw ("core/dependencies.lp")
+import raw ("core/control-context.lp")
+import raw ("core/unit-tests.lp")
+
+InstallationStatus = type variant(NOT_INSTALLED, INSTALLED).
+
+interface(adhoc){
+ pre function expectNoErrors:: InstallationStatus {
+ case Error {NOT_INSTALLED}
+ case Success {INSTALLED}
+ }
+}
+
+interface(extern-c){
+ libFake = library:: pkgconfig("libxml-2.0").
+
+ include {
+ libFake = ["stdio.h", "stdlib.h"]
+ }.
+}
+
+exec = pre function(comm:: string) {
+ result = system(comm):: num.
+
+ if (result==0)::InstallationStatus
+ {ad hoc "Success"}
+ else {ad hoc "Error"}
+}
+
+start = function:: int; entry {
+ context:: goal(artefact(gcc)).
+
+ provideGoals()
+}
+
+provideGoals = function:: int {
+ loop context ("goal") {
+ provideArtefact()
+ }
+}
+
+provideArtefact = function:: int{
+ switch (actionEXISTS())::int
+
+ case INSTALLED {0}
+
+ case NOT_INSTALLED {
+ sequence [
+ provideDependencies(),
+ actionPROVIDE()
+ ]
+ }
+
+ case default {-1}
+}
+
+provideDependencies = function::int {
+ rule context:: childs(Child)
+ case artefact(Item) {
+ artefact_depends(Item, Child)
+ }
+
+ loop context ("childs") {
+ provideArtefact()
+ }
+}
+
+case context:: artefact(subversion) {
+ actionEXISTS = function::int {
+ context:: expectNoErrors.
+
+ exec("svn --version")
+ }
+
+ actionPROVIDE = function::int {
+ context:: expectNoErrors.
+
+ exec("sudo apt-get install subversion")
+ }
+}
+
+actionEXISTS = function::int {
+ -1
+}
+
+actionPROVIDE = function::int {
+ -1
+}
+
+
+// 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"}
+}
+*/
diff --git a/scripts/xml/input.xreate b/scripts/testspass/xml-test1.xreate
similarity index 100%
rename from scripts/xml/input.xreate
rename to scripts/testspass/xml-test1.xreate
diff --git a/scripts/xml/xml-test1.xreate b/scripts/xml/xml-test1.xreate
new file mode 120000
index 0000000..a65ed28
--- /dev/null
+++ b/scripts/xml/xml-test1.xreate
@@ -0,0 +1 @@
+/private/prg/code/xreate/scripts/testspass/xml-test1.xreate
\ No newline at end of file

Event Timeline