No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:38 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.gitignore b/.gitignore
index b3fe7b7..f27ef5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,68 +1,72 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*-build-*
# QtCreator
*.autosave
coco/*.old
coco/*~
*~
cpp/build-*/*
cpp/xreate-debug/*
cpp/xreate-release/*
cpp/.idea
cpp/CMakeLists.txt.user*
hs/*
project/*
nb*.xml
.*
target/*
-/tools/phabricator/xreate-frontend/nbproject/private/
\ No newline at end of file
+/tools/phabricator/xreate-frontend/nbproject/private/
+documentation/trash4/
+CMakeFiles/
+gen-cpp/
+gen-php
diff --git a/coco/Taste-example.ATG b/coco/Taste-example.ATG
deleted file mode 100644
index 1ada837..0000000
--- a/coco/Taste-example.ATG
+++ /dev/null
@@ -1,147 +0,0 @@
-COMPILER Taste
-
-Proc curProc; // current program unit (procedure or main program)
-
-CHARACTERS
- letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
- digit = "0123456789".
- cr = '\r'.
- lf = '\n'.
- tab = '\t'.
-
-TOKENS
- ident = letter {letter | digit}.
- number = digit {digit}.
-
-COMMENTS FROM "/*" TO "*/" NESTED
-COMMENTS FROM "//" TO lf
-
-IGNORE cr + lf + tab
-
-
-
-PRODUCTIONS
-
-/*=================== Program and declarations ============================*/
-
-Taste (. String name; .)
-= "program"
- Ident<out name> (. curProc = new Proc(name, null, this); .)
- "{"
- { VarDecl | ProcDecl }
- "}" (. for (Obj obj: curProc.locals) {
- if (obj instanceof Proc) ((Proc)obj).dump();
- } .).
-/*------------------------------------------------------------------------*/
-VarDecl (. String name; Type type; .)
-= Typ<out type>
- Ident<out name> (. curProc.add(new Var(name, type)); .)
- { ',' Ident<out name> (. curProc.add(new Var(name, type)); .)
- } ';'.
-/*------------------------------------------------------------------------*/
-Typ<out Type type>
-= (. type = Type.INT; .)
- ( "int"
- | "bool" (. type = Type.BOOL; .)
- ).
-/*------------------------------------------------------------------------*/
-ProcDecl (. String name; .)
-= "void"
- Ident<out name> (. Proc oldProc = curProc;
- curProc = new Proc(name, oldProc, this);
- oldProc.add(curProc); .)
- '(' ')'
- Block<out curProc.block> (. curProc = oldProc; .).
-
-
-/*============================= Statements ===============================*/
-
-Block<out Block b> (. Stat s; .)
-= '{' (. b = new Block(); .)
- { Stat<out s> (. b.add(s); .)
- | VarDecl
- }
- '}'
- .
-/*------------------------------------------------------------------------*/
-Stat<out Stat s> (. String name; Expr e; Stat s2; Block b; .)
-= (. s = null; .)
-( Ident<out name> (. Obj obj = curProc.find(name); .)
- ( '='
- Expr<out e> ';' (. s = new Assignment(obj, e); .)
- | '(' ')' ';' (. s = new Call(obj); .)
- )
-
-| "if"
- '(' Expr<out e> ')'
- Stat<out s> (. s = new If(e, s); .)
- [ "else" Stat<out s2> (. s = new IfElse(s, s2); .)
- ]
-
-| "while"
- '(' Expr<out e> ')'
- Stat<out s> (. s = new While(e, s); .)
-
-| "read"
- Ident<out name> ';' (. s = new Read(curProc.find(name)); .)
-
-| "write"
- Expr<out e> ';' (. s = new Write(e); .)
-
-| Block<out b> (. s = b; .)
-).
-
-
-
-/*============================ Expressions ===============================*/
-
-Expr<out Expr e> (. Operator op; Expr e2; .)
-= SimExpr<out e>
- [ RelOp<out op>
- SimExpr<out e2> (. e = new BinExpr(e, op, e2); .)
- ].
-/*------------------------------------------------------------------------*/
-SimExpr<out Expr e> (. Operator op; Expr e2; .)
-= Term<out e>
- { AddOp<out op>
- Term<out e2> (. e = new BinExpr(e, op, e2); .)
- }.
-/*------------------------------------------------------------------------*/
-Term<out Expr e> (. Operator op; Expr e2; .)
-= Factor<out e>
- { MulOp<out op>
- Factor<out e2> (. e = new BinExpr(e, op, e2); .)
- }.
-/*------------------------------------------------------------------------*/
-Factor<out Expr e> (. String name; .)
-= (. e = null; .)
- ( Ident<out name> (. e = new Ident(curProc.find(name)); .)
- | number (. e = new IntCon(Integer.parseInt(t.val)); .)
- | '-' Factor<out e> (. e = new UnaryExpr(Operator.SUB, e); .)
- | "true" (. e = new BoolCon(true); .)
- | "false" (. e = new BoolCon(false); .)
- ).
-/*------------------------------------------------------------------------*/
-Ident<out String name>
-= ident (. name = t.val; .).
-/*------------------------------------------------------------------------*/
-AddOp<out Operator op>
-= (. op = Operator.ADD; .)
- ( '+'
- | '-' (. op = Operator.SUB; .)
- ).
-/*------------------------------------------------------------------------*/
-MulOp<out Operator op>
-= (. op = Operator.MUL; .)
- ( '*'
- | '/' (. op = Operator.DIV; .)
- ).
-/*------------------------------------------------------------------------*/
-RelOp<out Operator op>
-= (. op = Operator.EQU; .)
- ( "=="
- | '<' (. op = Operator.LSS; .)
- | '>' (. op = Operator.GTR; .)
- ).
-
-END Taste.
diff --git a/coco/Taste-example.TAS b/coco/Taste-example.TAS
deleted file mode 100644
index ff122d6..0000000
--- a/coco/Taste-example.TAS
+++ /dev/null
@@ -1,31 +0,0 @@
-
-// This is a test program which can be compiled by the Taste-compiler.
-// It reads a sequence of numbers and computes the sum of all integers
-// up to these numbers.
-
-program Test {
- int i;
-
- void Foo() {
- int a, b, max;
- read a; read b;
- if (a > b) max = a; else max = b;
- write max;
- }
-
- void SumUp() {
- int sum;
- sum = 0;
- while (i > 0) { sum = sum + i; i = i - 1; }
- write sum;
- }
-
- void Main() {
- read i;
- while (i > 0) {
- SumUp();
- read i;
- }
- }
-}
-
diff --git a/coco/gen-grammar b/coco/gen-grammar
index 814c770..66a5acd 100755
--- a/coco/gen-grammar
+++ b/coco/gen-grammar
@@ -1 +1,4 @@
-cococpp -frames ./generator-frames ./xreate.ATG
+COCO_PATH=/opt/coco-cpp/
+
+echo "Run coco generator: "
+$COCO_PATH/Coco ./xreate.ATG -frames $COCO_PATH
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index 242d665..afc8fda 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,518 +1,549 @@
//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 = "::".
+ lse = "<=".
+ lss = "<".
+ gte = ">=".
+ gtr = ">".
+
+ ne1 = "!=".
+ ne2= "<>".
+
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; .)
+FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .)
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));.)
+['(' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
+{',' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom <Identifier_t>(argName), move(binding));.)
} ')']
[ tagcolon
( IF(flagIsPrefunct) FnTag<f>
| Type<typOut> (. f->setReturnType(typOut); .)
)
{';' FnTag<f> }]
-BDecl<entry> (. entry->__body.bindType(move(typOut));.)
+BDecl<entry> (. entry->getBody().bindType(move(typOut));.)
.
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); .)
- .
+ ("string" | "num" | "int" | "i8" | "i32" | "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)); .)
+VDecl<CodeScope* f> = (. std::wstring vname; Expression e;.)
+Ident<vname> assign ExprTyped<e> (. f->addDeclaration(Atom<Identifier_t>(vname), 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)); .)
+MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
+{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
//TODO forbid multiple body declaration (ExprTyped)
-BDecl<CodeScope* scope> = (. Expression body; TypeAnnotation typ; pushContextScope(scope); .)
+BDecl<CodeScope* scope> = (. Expression body; pushContextScope(scope); .)
'{' { (RuleContextDecl<scope> | ContextDecl<scope> '.'
| IF(checkAssignment()) VDecl<scope> '.'
- | ExprTyped<body, typ> (. scope->setBody(body); popContextScope();.)
+ | ExprTyped<body> (. 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.bindType(move(typIf)); .)
+IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(context.scope)); .)
+"if" '(' Expr<cond> ')' (. e = Expression(Operator::IF, {cond}); .)
+tagcolon ExprAnnotations<e>
+BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
-LoopDecl<Expression& e, TypeAnnotation& typOut> =
- (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; TypeAnnotation typEl, typAcc;
+LoopDecl<Expression& e> =
+ (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl;
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});
+ ("map" '(' Expr<eIn> implic Ident<varEl> (. e = Expression(Operator::MAP, {eIn}); .)
+ tagcolon ExprAnnotations<tagsEl> ')' tagcolon ExprAnnotations<e> BDecl<&*block>
+ (.
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<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(typOut));
- e.addBlock(block);
- .)
-
+ block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
+ e.addBlock(block);
+ .)
+
+ |"fold"
+ ("inf" '(' Expr<eAcc> implic Ident<varAcc> ')'
+ (.
+ e = Expression(Operator::FOLD_INF, {eAcc});
+ e.addBindings({Atom<Identifier_t>(varAcc)});
+ .)
+ tagcolon ExprAnnotations<e> BDecl<&*block>
+ (.
+ block->addBinding(Atom<Identifier_t>(varAcc), Expression());
+ e.addBlock(block);
+ .)
+
+ | '(' Expr<eIn> implic Ident<varEl> tagcolon ExprAnnotations<tagsEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc>')'
+ (.
+ e = Expression(Operator::FOLD, {eIn, eAcc});
+ e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
+ .)
+ tagcolon ExprAnnotations<e> BDecl<&*block>
+ (.
+
+ block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
+ block->addBinding(Atom<Identifier_t>(varAcc), Expression());
+ 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; .)
+ ( "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 ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
)
]
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; .)
+CaseParam<CodeScope* scope, Expression& guard> = (. Expression condition; .)
(
IF(checkAssignment()) VDecl<scope>
- | ExprTyped<condition, argtyp> (. guard.addArg(move(condition)); .)
+ | ExprTyped<condition> (. 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)); .)
-
- }]
-.
+ExprAnnotations<Expression& e> = (. TypeAnnotation typ; Expression tag; e.tags.clear();.)
+Type<typ> (. e.bindType(move(typ)); .)
+ {';' MetaSimpExpr<tag> (. e.tags.emplace(tag.getValueString(), tag); .)
+ }.
+
+ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
Expr< Expression& e> (. Operator op; Expression e2; .)
-= SimExpr< e>
- [ RelOp< op>
-SimExpr< e2> (. e = Expression(op, {e, 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; .)
+Factor< Expression& e> (. std::wstring name; e = Expression(); .)
=
(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>
+ | LoopDecl<e>
+ | IfDecl<e>
| 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> ')'
+ | '(' ExprTyped<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)); .)
+ {',' Ident<key> '=' Expr<val> (.e.addArg(Expression(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)); .)
+[ Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
+(".." Expr<eTo> (. e.addArg(Expression(eTo)); e.setOp(Operator::LIST_RANGE); .)
+ |{',' Expr<eFrom> (. e.addArg(Expression(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)); .)
+CalleeParams<Expression& e> = (. Expression e2; .)
+ ExprTyped<e2> (. e.addArg(Expression(e2)); .)
+ {',' ExprTyped<e2> (. e.addArg(Expression(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; .)
+= (. op = Operator::EQU; .)
( equal
- | '<' (. op = Operator::LSS; .)
- | '>' (. op = Operator::GTR; .)
+ | (ne1 | ne2) (. op = Operator::NE; .)
+
+ | lse (. op = Operator::LSE; .)
+ | lss (. op = Operator::LSS; .)
+
+ | gte (. op = Operator::GTE; .)
+ | gtr (. op = Operator::GTR; .)
+
).
END Xreate.
diff --git a/config/default.json b/config/default.json
index 08e9bd6..8cbfb4f 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,59 +1,73 @@
{
"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",
"function_demand" : "bind_function_demand",
"scope_decision": "bind_scope_decision"
},
+ "context" : {
+ "decisions":{
+ "dependent": "resolution_dependency"
+ },
+ },
+
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
- "template": "context",
+ "template": "default",
"templates": {
- "basic": "EntryFunction*",
"default": "*-",
- "types": "Types*-",
+
+ "basic": "Basic.*",
+ "ast": "AST.*",
+ "cfa": "CFA.*",
+ "dfa": "DFA.*",
+ "compilation": "Compilation.*",
"containers": "Containers*-",
- "ast": "AST*",
- "non-containers": "*-Containers*",
+ "diagnostic": "Diagnostic.*",
+ "serializer": "ExpressionSerializer.*",
+ "externc": "InterfaceExternC.*",
+ "context": "ExpressionSerializer.*:Context.*",
+ "types": "Types.*-",
"log": "Logging*",
- "clang": "ClangAPI*",
- "cfg": "CFG.*",
- "skip": "SkipDetection*",
+ "clang": "ClangAPI.*",
+ "skip": "SkipDetection*:Adhoc_Loop_SkipDetection.*",
"raw-xml": "libxml2*",
"xml": "Xml.*",
- "adhocs": "ExpressionSerializer.*:Adhoc.*:Context.*",
- "context": "ExpressionSerializer.*:Context.*",
- "installation": "Compilation.*:Sprint1.*"
+ "installation": "Compilation.*:Sprint1.*",
+ "exploitation": "Exploitation.*",
+ "loops": "Loop.*",
+ "dsl": "Interpretation.*",
+ "adhocs": "Adhoc.*",
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index b64dbed..71152a3 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,228 +1,225 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
# BUILD OPTIONS
#======================
set(XREATE_DEFINITIONS
-D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DWITH_THREADS=1
)
add_definitions(${XREATE_DEFINITIONS})
add_compile_options(-Winvalid-pch -std=c++14 -fPIC)
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED CONFIG PATHS /opt/llvm-3.8.0-0.x86_64/usr/share/llvm/cmake NO_DEFAULT_PATH)
set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-tools")
#include(PCH_GCC4_v2)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message ("LLVM LIB PATH:" ${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}")
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message("LLVM defs: " ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support)
message("LLVM libs: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
${LLVM_LIBRARY_DIRS}/libclangCodeGen.so
${LLVM_LIBRARY_DIRS}/libclangASTMatchers.so
${LLVM_LIBRARY_DIRS}/libclangQuery.so
${LLVM_LIBRARY_DIRS}/libclangTooling.so
${LLVM_LIBRARY_DIRS}/libclangFrontend.so
${LLVM_LIBRARY_DIRS}/libclangSerialization.so
${LLVM_LIBRARY_DIRS}/libclangDriver.so
${LLVM_LIBRARY_DIRS}/libclangParse.so
${LLVM_LIBRARY_DIRS}/libclangSema.so
${LLVM_LIBRARY_DIRS}/libclangAnalysis.so
${LLVM_LIBRARY_DIRS}/libclangAST.so
${LLVM_LIBRARY_DIRS}/libclangEdit.so
${LLVM_LIBRARY_DIRS}/libclangLex.so
${LLVM_LIBRARY_DIRS}/libclangBasic.so
)
#find_package(Clang REQUIRED clangTooling libClang)
message(STATUS "CLANG LIBS: " ${CLANG_LIBS})
# POTASSCO
#======================
set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
${POTASSCO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS})
link_directories(${LIBCLASP_PATH})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
set(COCO_SOURCE_FILES
${COCO_PATH}/Parser.cpp
${COCO_PATH}/Scanner.cpp)
INCLUDE_DIRECTORIES(${COCO_PATH})
add_custom_command(OUTPUT ${COCO_SOURCE_FILES}
COMMAND ${COCO_PATH}/gen-grammar
WORKING_DIRECTORY ${COCO_PATH}
MAIN_DEPENDENCY ${COCO_PATH}/xreate.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
set(SOURCE_FILES
pass/compilepass.cpp
+ pass/interpretationpass.cpp
+ compilation/targetinterpretation.cpp
ast.cpp
ExternLayer.cpp
attachments.cpp
- pass/interpretationpass.cpp
- compilation/targetinterpretation.cpp
analysis/cfagraph.cpp
analysis/dfagraph.cpp
analysis/aux.cpp
compilation/containers.cpp
compilation/advanced.cpp
compilation/transformations.cpp
analysis/DominatorsTreeAnalysisProvider.cpp
clasplayer.cpp
compilation/latecontextcompiler2.cpp
query/context.cpp
#compilation/latecontextcompiler.cpp
serialization/expressionserializer.cpp
serialization/expressionserializer2.cpp
llvmlayer.cpp
utils.cpp
passmanager.cpp
pass/abstractpass.cpp pass/dfapass.cpp
pass/cfapass.cpp
pass/loggerpass.cpp
pass/adhocpass.cpp
#pass/rulespass.cpp #
query/containers.cpp
query/ptrvalid.cpp
contextrule.cpp
-
- #${POTASSCO_PATH}/app/shared/src/clingocontrol.cc
- #${POTASSCO_PATH}/app/pyclingo/src/clingo_lib.cc
)
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} ${LIBCLASP_LIBS})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_PATH}
${JEAYESON_INCLUDE_PATH}
${LLVM_INCLUDE_DIRS}
${POTASSCO_INCLUDE_PATH}
)
get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
message("definitions all: " ${DEFINITIONS_ALL})
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL})
get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS)
message("compilations all: " ${COMPILATION_OPTIONS_ALL})
target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL})
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY
INTERFACE_LINK_LIBRARIES ${LLVM_LIBS} ${CLANG_LIBS} tbb
)
#set (LINK_INTERFACE_LIBRARIES "")
# FUNCTION(PREPEND var prefix)
# SET(listVar "")
# FOREACH(f ${ARGN})
# LIST(APPEND listVar "${prefix}/${f}")
# ENDFOREACH(f)
# SET(${var} "${listVar}" PARENT_SCOPE)
# ENDFUNCTION(PREPEND)
#set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4")
#cotire(xreate)
# 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)
# 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)
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 48f3f85..8874a23 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,299 +1,310 @@
//
// 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 "clang/Lex/PreprocessorOptions.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include "../../vendors/clang-codegen-private-3.8/CodeGenModule.h"
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)
: __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;
+ //cut unwanted symbols at the end
+ char symbLast = linebuf[linelen-1 ];
+ if (symbLast == ' ' || symbLast == '\n') linebuf[linelen-1] = 0;
+
+ //print header for debug purposes
llvm::outs() << '<' << linebuf << "> ";
- args.push_back(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);
- }
+ if (linebuf[0]=='\n') continue;
+ if (linelen==1 && linebuf[0]==' ') continue;
+
+ //cut unwanted symbols at the end
+ char symbLast = linebuf[linelen-1 ];
+ if (symbLast == ' ' || symbLast == '\n') linebuf[linelen-1] = 0;
- llvm::outs() << '<' << linebuf << "> ";
- free(linebuf);
- linebuf = 0;
+ //cut unwanted symbols at the beginning
+ if (linelen>1 && linebuf[0] == '-' && linebuf[1] == 'l'){
+ libs.push_back(linebuf + 2);
+
+ } else {
+ libs.push_back(linebuf);
+ }
+
+ //print lib name for debug purposes
+ 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'
+ // TODO -EXTERN01.DIP, 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);
__llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayoutString());
-
+
std::unique_ptr<clang::HeaderSearchOptions> __hso(new HeaderSearchOptions());
std::unique_ptr<clang::PreprocessorOptions> __ppo(new PreprocessorOptions());
-
+
__cgm.reset(new CodeGen::CodeGenModule(
- ast->getASTContext(),
-
+ ast->getASTContext(),
+
*__hso,
*__ppo,
- *__cgo,
+ *__cgo,
*__llvm->module,
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());
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/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp
index 360035b..7ccf9e0 100644
--- a/cpp/src/analysis/dfagraph.cpp
+++ b/cpp/src/analysis/dfagraph.cpp
@@ -1,237 +1,250 @@
#include "analysis/dfagraph.h"
#include "analysis/aux.h"
#include <list>
using namespace xreate;
using namespace xreate::analysis;
using namespace std;
-namespace xreate {namespace analysis {
-void
-DFAGraph::print(std::ostringstream& output) const {
- std::set<SymbolPacked> symbols;
+namespace xreate {
+ namespace analysis {
+
+ void
+ DFAGraph::print(std::ostringstream& output) const {
+ std::set<SymbolPacked> symbols;
+
+ output << endl << "%\t\tStatic analysis: DFA" << endl;
+
+ std::vector<std::pair<SymbolPacked, SymbolPacked>>::const_iterator i1;
+ std::vector<DFGConnection>::const_iterator i2;
+
+ boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
+ for (i1 = this->__edges.begin(), i2 = this->__data.begin(); i1 != this->__edges.end(); ++i1, ++i2) {
+ string edgeName;
+ switch (*i2) {
+ case DFGConnection::WEAK: edgeName = "weak";
+ break;
+ case DFGConnection::STRONG: edgeName = "strong";
+ break;
+ case DFGConnection::PROTOTYPE: edgeName = "proto";
+ break;
+ }
- output << endl << "%\t\tStatic analysis: DFA" << endl;
+ output << formatDfaConnection
+ % formatSymbol(i1->first)
+ % formatSymbol(i1->second)
+ % edgeName
+ << " %" << this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second)
+ << endl;
- std::vector<std::pair<SymbolPacked, SymbolPacked>>::const_iterator i1;
- std::vector<DFGConnection>::const_iterator i2;
+ symbols.insert(i1->first);
+ symbols.insert(i1->second);
+ }
- boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
- for (i1= this->__edges.begin(), i2 = this->__data.begin(); i1!= this->__edges.end(); ++i1, ++i2 )
- {
- string edgeName;
- switch (*i2)
- {
- case DFGConnection::WEAK: edgeName = "weak"; break;
- case DFGConnection::STRONG: edgeName = "strong"; break;
- case DFGConnection::PROTOTYPE: edgeName = "proto"; break;
- }
+ boost::format formatDfaDependency("dfa_dependency(%1%, %2%).");
+ for (auto i = this->__dependencies.begin(); i != this->__dependencies.end(); ++i) {
+ output << formatDfaDependency
+ % formatSymbol(i->first)
+ % formatSymbol(i->second)
+ << " %"
+ << this->__clasp->getHintForPackedSymbol(i->first) << " - "
+ << this->__clasp->getHintForPackedSymbol(i->second)
+ << endl;
+ }
- output << formatDfaConnection
- %formatSymbol(i1->first)
- %formatSymbol(i1->second)
- %edgeName
- << " %" <<this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second)
- <<endl;
+ boost::format formatBind("bind(%1%, %2%).");
+ for (const pair<SymbolPacked, Expression>& tag : this->__tags) {
+ for (string variant : xreate::analysis::compile(tag.second)) {
+ output << formatBind
+ % formatSymbol(tag.first)
+ % (variant)
+ << "%" << this->__clasp->getHintForPackedSymbol(tag.first)
+ << endl;
+ }
- symbols.insert(i1->first);
- symbols.insert(i1->second);
- }
-
- boost::format formatDfaDependency("dfa_dependency(%1%, %2%).");
- for (auto i= this->__dependencies.begin(); i!= this->__dependencies.end(); ++i){
- output<<formatDfaDependency
- %formatSymbol(i->first)
- %formatSymbol(i->second)
- << " %"
- << this->__clasp->getHintForPackedSymbol(i->first) << " - "
- << this->__clasp->getHintForPackedSymbol(i->second)
- <<endl;
- }
-
- boost::format formatBind("bind(%1%, %2%).");
- for (const pair<SymbolPacked, Expression>& tag: this->__tags)
- {
- for (string variant: xreate::analysis::compile(tag.second)) {
- output << formatBind
- % formatSymbol(tag.first)
- % (variant)
- << "%" << this->__clasp->getHintForPackedSymbol(tag.first)
- << endl;
+ symbols.insert(tag.first);
+ }
+
+ for (const SymbolPacked& s : symbols) {
+ output << "v(" << formatSymbol(s) << ")."
+ << " %" << this->__clasp->getHintForPackedSymbol(s)
+ << endl;
+ }
}
- symbols.insert(tag.first);
- }
+ class VisitorAddTag : public boost::static_visitor<> {
+ public:
- for (const SymbolPacked& s: symbols)
- {
- output << "v(" << formatSymbol(s) << ")."
- << " %" << this->__clasp->getHintForPackedSymbol(s)
- <<endl;
- }
-}
+ void operator()(const SymbolPacked& symbol) {
+ __graph->__tags.emplace(symbol, move(__tag));
+ }
-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()(SymbolTransient& symbol){
- symbol.tags.push_back(move(__tag));
- }
+ void operator()(const SymbolInvalid& symbol) {
+ assert(false && "Undefined behaviour");
+ }
- 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) {
+ switch (__link) {
+ case DFGConnection::WEAK:
+ {
+ //virtual symbol to hold transient annotations
+ SymbolPacked symbPivot = __graph->createAnonymousSymbol(symbolFrom.scope);
+
+ __graph->addConnection(symbPivot, symbolFrom, DFGConnection::STRONG);
+ __graph->addConnection(__nodeTo, symbPivot, DFGConnection::WEAK);
+ break;
+ }
+
+ case DFGConnection::STRONG:
+ {
+ for (const Expression& tag : symbolFrom.tags) {
+ __graph->__tags.emplace(__nodeTo, tag);
+ }
+ break;
+ }
+
+ default:
+ assert(false && "Undefined behavior");
+ }
+ }
+
+ void operator()(const SymbolInvalid&) {
+ if (__link == DFGConnection::STRONG) return;
+ if (__link == DFGConnection::WEAK) return;
- VisitorAddTag(DFAGraph* const dfagraph, Expression&& tag):
- __graph(dfagraph), __tag(tag) {}
+ assert(false && "Undefined behavior");
+ }
- private:
- DFAGraph* const __graph;
- Expression __tag;
-};
+ VisitorAddLink(DFAGraph * const dfagraph, const SymbolPacked& nodeTo, DFGConnection link) :
+ __graph(dfagraph), __nodeTo(nodeTo), __link(link) {
+ }
-class VisitorAddLink: public boost::static_visitor<> {
-public:
- void operator()(const SymbolPacked& nodeFrom){
- if (!__graph->isConnected(__nodeTo, nodeFrom))
+ private:
+ DFAGraph * const __graph;
+ SymbolPacked __nodeTo;
+ DFGConnection __link;
+ };
+
+ class VisitorGetDependencyConnection : public boost::static_visitor<list<SymbolPacked>>
{
- __graph->__edges.emplace_back(__nodeTo, nodeFrom);
- __graph->__data.push_back(__link);
+ public:
+
+ list<SymbolPacked>
+ operator()(const SymbolPacked & nodeFrom) {
+ return
+ {
+ nodeFrom
+ };
+ }
- DFAGraph::EdgeId eid = __graph->__edges.size()-1;
- __graph->__outEdges.emplace(nodeFrom, eid);
- }
- }
+ list<SymbolPacked>
+ operator()(const SymbolTransient & nodeFrom) {
+ return nodeFrom.dependencies;
+ }
- void operator()(const SymbolTransient& symbolFrom){
- switch (__link){
- case DFGConnection::WEAK: {
- //virtual symbol to hold transient annotations
- SymbolPacked symbPivot = __graph->createAnonymousSymbol(symbolFrom.scope);
+ list<SymbolPacked>
+ operator()(const SymbolInvalid&) {
+ assert(false && "Undefined behavior");
+ }
- __graph->addConnection(symbPivot, symbolFrom, DFGConnection::STRONG);
- __graph->addConnection(__nodeTo, symbPivot, DFGConnection::WEAK);
- break;
+ VisitorGetDependencyConnection(DFAGraph * const g) : graph(g) {
}
+ DFAGraph * const graph;
+ };
+
+ class VisitorSetDependencyConnection : public boost::static_visitor<> {
+ public:
+
+ void operator()(SymbolPacked& nodeTo) {
+ VisitorGetDependencyConnection visitorGetDepenencies(graph);
+ auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
- case DFGConnection::STRONG: {
- for (const Expression& tag: symbolFrom.tags){
- __graph->__tags.emplace(__nodeTo, tag);
+ for (const SymbolPacked& dep : deps) {
+ graph->__dependencies.emplace(nodeTo, dep);
}
- break;
}
- default:
- assert(false && "Undefined behavior");
- }
- }
+ void operator()(SymbolTransient& nodeTo) {
+ VisitorGetDependencyConnection visitorGetDepenencies(graph);
+ auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
- void operator()(const SymbolInvalid&){
- if (__link == DFGConnection::STRONG) return;
- if (__link == DFGConnection::WEAK) return;
+ for (const SymbolPacked& dep : deps) {
+ nodeTo.dependencies.push_back(dep);
+ }
+ }
- assert(false && "Undefined behavior");
- }
+ void operator()(SymbolInvalid&) {
+ assert(false && "Undefined behavior");
+ }
- VisitorAddLink(DFAGraph* const dfagraph, const SymbolPacked& nodeTo, DFGConnection link):
- __graph(dfagraph), __nodeTo(nodeTo), __link(link) {}
+ VisitorSetDependencyConnection(DFAGraph * const g, SymbolNode s) : graph(g), nodeFrom(s) {
+ }
+ DFAGraph * const graph;
+ SymbolNode nodeFrom;
+ };
-private:
- DFAGraph* const __graph;
- SymbolPacked __nodeTo;
- DFGConnection __link;
-};
+ bool
+ DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom) {
+ auto range = __outEdges.equal_range(identifierFrom);
-class VisitorGetDependencyConnection: public boost::static_visitor<list<SymbolPacked>> {
-public:
- list<SymbolPacked>
- operator()(const SymbolPacked& nodeFrom){
- return {nodeFrom};
- }
-
- list<SymbolPacked>
- operator()(const SymbolTransient& nodeFrom){
- return nodeFrom.dependencies;
- }
-
- list<SymbolPacked>
- operator()(const SymbolInvalid&){
- assert(false && "Undefined behavior");
- }
-
- VisitorGetDependencyConnection(DFAGraph* const g): graph(g){}
- DFAGraph* const graph;
-};
-
-class VisitorSetDependencyConnection: public boost::static_visitor<> {
-public:
- void operator()(SymbolPacked& nodeTo){
- VisitorGetDependencyConnection visitorGetDepenencies(graph);
- auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
-
- for (const SymbolPacked& dep: deps){
- graph->__dependencies.emplace(nodeTo, dep);
+ for (std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge) {
+ if (__edges[edge->second].second == identifierTo)
+ return true;
+ }
+
+ return false;
}
- }
-
- void operator()(SymbolTransient& nodeTo){
- VisitorGetDependencyConnection visitorGetDepenencies(graph);
- auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
-
- for (const SymbolPacked& dep: deps){
- nodeTo.dependencies.push_back(dep);
+
+ void
+ DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
+ VisitorAddLink visitor(this, nodeTo, link);
+ boost::apply_visitor(visitor, nodeFrom);
}
- }
-
- void operator()(SymbolInvalid&){
- assert(false && "Undefined behavior");
- }
-
- VisitorSetDependencyConnection(DFAGraph* const g, SymbolNode s): graph(g), nodeFrom(s){}
- DFAGraph* const graph;
- SymbolNode nodeFrom;
-};
-
-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::addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom){
- VisitorSetDependencyConnection visitor(this, identifierFrom);
- boost::apply_visitor(visitor, identifierTo);
-}
-
-void
-DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) {
- VisitorAddTag visitor(this, move(tag));
- boost::apply_visitor(visitor, node);
-}
-
-SymbolPacked
-DFAGraph::createAnonymousSymbol(const ScopePacked& scope){
- return SymbolPacked{__countAnonymousSymbols++, scope, true};
-}
-
-}}
\ No newline at end of file
+ void
+ DFAGraph::addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom) {
+ VisitorSetDependencyConnection visitor(this, identifierFrom);
+ boost::apply_visitor(visitor, identifierTo);
+ }
+
+ void
+ DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) {
+ VisitorAddTag visitor(this, move(tag));
+ boost::apply_visitor(visitor, node);
+ }
+
+ SymbolPacked
+ DFAGraph::createAnonymousSymbol(const ScopePacked& scope) {
+ return SymbolPacked{__countAnonymousSymbols++, scope, true};
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 1552a18..27b3468 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,774 +1,816 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <clasplayer.h>
using namespace std;
namespace xreate{
class ExpressionHints{
public:
static bool
isStringValueValid(const Expression& e){
switch (e.__state){
case Expression::INVALID:
case Expression::VARIANT:
assert(false);
case Expression::IDENT:
case Expression::STRING:
return true;
case Expression::NUMBER:
case Expression::BINDING:
return false;
case Expression::COMPOUND: {
switch (e.op){
case Operator::CALL:
case Operator::INDEX:
return true;
default: return false;
}
}
}
return false;
}
static bool
isDoubleValueValid(const Expression& e){
switch (e.__state){
case Expression::NUMBER:
return true;
case Expression::INVALID:
case Expression::VARIANT:
assert(false);
case Expression::IDENT:
case Expression::STRING:
case Expression::COMPOUND:
case Expression::BINDING:
return false;
}
return false;
}
};
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 = move(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);
}
bool
Expression::isDefined() const{
return (__state != BINDING);
}
Expression::Expression()
: __state(INVALID), op(Operator::NONE)
{}
bool
Expression::operator==(const Expression& other) const{
assert(!this->blocks.size());
assert(!other.blocks.size());
if (this->__state != other.__state) return false;
if (ExpressionHints::isStringValueValid(*this)){
if (this->__valueS != other.__valueS) return false;
}
if (ExpressionHints::isDoubleValueValid(*this)){
if (this->__valueD != other.__valueD) return false;
}
if (this->__state != Expression::COMPOUND){
return true;
}
if (this->operands.size() != other.operands.size()){
return false;
}
for (size_t i=0; i<this->operands.size(); ++i){
if (!(this->operands[i]==other.operands[i])) return false;
}
return true;
}
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(), __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(), move(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, &this->__functions);
}
std::list<ManagedFnPtr>
AST::getAllFunctions() const{
const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
for (size_t i=0; i<size; ++i){
result.push_back(ManagedFnPtr(i, &this->__functions));
}
return result;
}
//TASK select default specializations
std::list<ManagedFnPtr>
AST::getFunctionVariants(const std::string& name) const{
auto functions = __indexFunctions.equal_range(name);
std::list<ManagedFnPtr> result;
std::transform(functions.first, functions.second, inserter(result, result.end()),
[this](auto f){return ManagedFnPtr(f.second, &this->__functions);});
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){
// TODO get rid of findSymbol. Determine symbol while AST parsing. Re-find symbols not found while first pass.
// * move to codescope
// * use findSymbol to find Symbol
// * register var as alias to
// * ident __doubleValue holds VID of an alias
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)
{
string name = tag.getValueString();
__tags.emplace(move(name), move(tag));
}
const std::map<std::string, Expression>&
Function::getTags() const
{
return __tags;
}
CodeScope*
Function::getEntryScope() const
{
return __entry;
}
void
Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument)
{
__entry->addBinding(move(name), move(argument));
}
void
Function::setReturnType(const TypeAnnotation &rtyp)
{
+
__entry->__declarations[0].type = rtyp;
}
const std::string&
Function::getName() const
{
return __name;
}
Symbol
CodeScope::registerIdentifier(Atom <Identifier_t> &&name)
{
__identifiers.emplace(name.get(), ++__vCounter);
return {__vCounter, this};
}
void
CodeScope::addBinding(Atom <Identifier_t>&& name, Expression&& argument)
{
__bindings.push_back(name.get());
Symbol binding = registerIdentifier(move(name));
argument.__state = Expression::BINDING;
__declarations[binding.identifier] = move(argument);
}
void
CodeScope::addDeclaration(Atom <Identifier_t>&& name, Expression&& body)
{
Symbol s = registerIdentifier(move(name));
__declarations[s.identifier] = move(body);
}
CodeScope::CodeScope(CodeScope* parent)
:__parent(parent)
{}
CodeScope::~CodeScope()
{}
-
-
-
-
void
CodeScope::setBody(const Expression &body)
{
- __body = body;
+ __declarations[0] = body;
+}
+
+Expression&
+CodeScope::getBody(){
+ return __declarations[0];
}
Symbol
CodeScope::findSymbol(const std::string &name)
{
//search identifier in the current block
if (__identifiers.count(name))
{
VID vId = __identifiers.at(name);
Symbol result{vId, this};
return result;
}
//search in the parent scope
if (__parent)
{
return __parent->findSymbol(name);
}
//exception: Ident not found
std::cout << "Unknown symbol: "<< name << std::endl;
assert(false && "Symbol not found");
}
const Expression&
CodeScope::findDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
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)
{
//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);
}
+
+bool operator < (const Expression&a, const Expression&b) {
+if (a.__state != b.__state) return a.__state < b.__state;
+assert(a.__state != Expression::INVALID);
+switch(a.__state) {
+ case Expression::IDENT:
+ case Expression::STRING:
+ case Expression::VARIANT:
+ return a.getValueString() < b.getValueString();
+
+ case Expression::NUMBER:
+ return a.getValueDouble() < b.getValueDouble();
+
+ case Expression::COMPOUND: {
+ assert(a.op == Operator::CALL);
+ assert(a.blocks.size()==0);
+ assert(b.blocks.size()==0);
+
+ if (a.operands.size() != b.operands.size()){
+ return (a.operands.size() < b.operands.size());
+ }
+
+ if (a.getValueString() != b.getValueString()){
+ return a.getValueString() < b.getValueString();
+ }
+
+ for(size_t i=0; i<a.operands.size(); ++i){
+ bool result = a.operands[i] < b.operands[i];
+ if (result) return true;
+ }
+
+ return false;
+ }
+
+ case Expression::BINDING:
+ case Expression::INVALID:
+ assert(false);
}
+return false;
+}
+}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index fbc2eb4..cd070ab 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,561 +1,562 @@
#ifndef AST_H
#define AST_H
#include "attachments.h"
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#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, Num, Int, I32, I8, Float, String,
};
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 == "num") {
__value = TypePrimitive::Num;
} else if (buffer == "int") {
__value = TypePrimitive::Int;
} else if (buffer == "i8") {
__value = TypePrimitive::I8;
} else if (buffer == "i32") {
__value = TypePrimitive::I32;
} else if (buffer == "float") {
__value = TypePrimitive::Float;
} 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, NE, NEG, LSS, LSE, GTR, GTE, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, FOLD_INF, 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);
//To update ExpressionHints in case of any changes
struct Expression {
friend class CodeScope;
friend class ClaspLayer;
friend class CFAPass;
friend class ExpressionHints;
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;
bool isDefined() const;
bool operator==(const Expression& other) const;
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT, BINDING
} __state = INVALID;
Operator op;
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
TypeAnnotation type;
mutable std::map<std::string, Expression> tags;
mutable Attachments tagsInternal;
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
};
+
+ bool operator< (const Expression&, const Expression&);
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<Expression, TagModifier> Tag;
struct Symbol {
VID identifier;
CodeScope * scope;
};
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);
+ Expression& getBody();
void addDeclaration(Atom <Identifier_t>&& name, Expression&& body);
void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
Symbol findSymbol(const std::string &name);
static const Expression& findDeclaration(const Symbol& symbol);
~CodeScope();
std::vector<std::string> __bindings;
- Expression __body; //TODO move __body to __declarations[0]
-
std::map<std::string, VID> __identifiers;
/**
* definition of return type has variable index Zero(0)
*/
//TODO move __definitions to SymbolsAttachments data
std::unordered_map<VID, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
VID __vCounter = 0;
CodeScope* __parent;
Symbol registerIdentifier(Atom <Identifier_t>&& name);
};
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
void addTag(Expression&& tag, const TagModifier mod);
void setReturnType(const TypeAnnotation& rtyp);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
Expression guardContext;
private:
std::map<std::string, Expression> __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;
};
template<>
struct AttachmentsStorage<Symbol> {
static Attachments*
get(const Symbol& s) {
return &s.scope->findDeclaration(s).tagsInternal;
}
};
template<>
struct AttachmentsStorage<Expression> {
static Attachments*
get(const Expression& e) {
return &e.tagsInternal;
}
};
class AST {
public:
AST();
//TASK extern and DFA interfaces move into addInterfaceData
/**
* DFA Interface
*/
void addDFAData(Expression&& data);
/**
* Extern Interface
*/
void addExternData(ExternData&& data);
void addInterfaceData(const ASTInterface& interface, Expression&& data);
void add(Function* f);
void add(MetaRuleAbstract* r);
ManagedScpPtr add(CodeScope* scope);
std::string getModuleName();
ManagedPtr<Function> findFunction(const std::string& name);
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
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/attachments.h b/cpp/src/attachments.h
index a62cd20..03b8711 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,124 +1,124 @@
//
// Created by pgess on 3/15/15.
//
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <map>
#include <assert.h>
#include <type_traits>
namespace xreate
{
//Attachments dictionary
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
- // static const unsigned int key (current unreserved - 5);
+ // static const unsigned int key (current unreserved - 6);
};
template<class T>
struct AttachmentsStorage
{
//static Attachments* get(const T&);
};
namespace detail {
template<class Typ>
typename std::enable_if<std::is_pointer<Typ>::value, void*>::type
__wrap(const Typ& value){
return value;
}
template<class Typ>
typename std::enable_if<std::is_pointer<Typ>::value, Typ>::type
__unwrap(void* value){
return reinterpret_cast<Typ>(value);
}
template<class Typ>
typename std::enable_if<! std::is_pointer<Typ>::value, void*>::type
__wrap(const Typ& value){
Typ* holder = new Typ(value);
return holder;
}
template<class Typ>
typename std::enable_if<! std::is_pointer<Typ>::value, Typ&>::type
__unwrap(void* value){
return *reinterpret_cast<Typ*>(value);
}
template<class Typ>
typename std::enable_if<std::is_pointer<Typ>::value, void>::type
__delete(void* value){
delete reinterpret_cast<Typ>(value);
}
template<class Typ>
typename std::enable_if<! std::is_pointer<Typ>::value, void>::type
__delete(void* value){
delete reinterpret_cast<Typ*>(value);
}
}
//TODO copy whole data from symbol to symbol: copy(sTo, sFrom);
class Attachments
{
public:
//TODO add specialization for pointers
template<class Tag>
using Data = typename AttachmentsDict<Tag>::Data;
template<class Holder, class Tag>
static void put(const Holder& holder, const Data<Tag>& data)
{
const unsigned int key = AttachmentsDict<Tag>::key;
Attachments* self = AttachmentsStorage<Holder>::get(holder);
void* dataWaste = self->put(key, detail::__wrap(data));
detail::__delete<Data<Tag>>(dataWaste);
}
template<class Holder, class Tag>
static Data<Tag>& get(const Holder& holder)
{
const unsigned int key = AttachmentsDict<Tag>::key;
Attachments* self = AttachmentsStorage<Holder>::get(holder);
return detail::__unwrap<Data<Tag>>(self->get(key));
}
template<class Holder, class Tag>
static Data<Tag> get(const Holder& holder, Data<Tag>&& dataDefault)
{
if (! exists<Holder, Tag>(holder)){
return dataDefault;
}
const unsigned int key = AttachmentsDict<Tag>::key;
Attachments* self = AttachmentsStorage<Holder>::get(holder);
return detail::__unwrap<Data<Tag>>(self->get(key));
}
template<class Holder, class Tag>
static bool exists(const Holder& holder)
{
const unsigned int key = AttachmentsDict<Tag>::key;
Attachments* self = AttachmentsStorage<Holder>::get(holder);
return self->exists(key);
}
private:
std::map<unsigned int, void*> __data;
void* put(unsigned int key, void *data);
void* get(unsigned int key);
bool exists(unsigned int key);
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index c1a6b7c..76509c6 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,274 +1,279 @@
#include "clasplayer.h"
#include <iostream>
#include "utils.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <gringo/scripts.hh>
#include "analysis/aux.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "analysis/cfagraph.h"
#include "analysis/dfagraph.h"
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::Symbol params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning->second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
- ClaspLayer::handlerSolution(Gringo::Model const &model) {
+ ClaspLayer::handleSolution(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::Symbol atom : model.atoms(clingo_show_type_atoms)) {
atom.print(cout);
cout <<" | "<< endl;
string atomName(atom.name().c_str());
if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){
string name = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__model.emplace(move(name), move(atom));
}
__model.emplace(atomName, move(atom));
}
return true;
}
void
ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) {
dataCFA.reset(graph);
}
-
- void
+
+ void
ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){
dataDFA.reset(graph);
}
-
+
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 xreate::analysis::compile(guard);
});
const list<string>& guards = xreate::analysis::multiplyLists(std::move(guardsRaw));
list<string> &&branches = xreate::analysis::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;
}
}
-
+
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();
- this->dataDFA->print(__partGeneral);
- this->dataCFA->print(__partGeneral);
-
+ if (this->dataDFA){
+ this->dataDFA->print(__partGeneral);
+ }
+
+ if (this->dataCFA){
+ this->dataCFA->print(__partGeneral);
+ }
+
DominatorsTreeAnalysisProvider providerDominators;
providerDominators.run(this);
providerDominators.print(__partGeneral);
-
+
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(), {}, 0);
ctl.add("base", {}, program.str());
ctl.ground({{"base", {}}}, nullptr);
// solve
Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
- this->handlerSolution(model);
+ this->handleSolution(model);
return true;
}, {});
if (result.satisfiable() == Gringo::SolveResult::Satisfiable) {
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* const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if (pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
-
- size_t
+
+ size_t
ClaspLayer::getScopesCount() const{
return __registryScopes.size();
}
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){
if (!symbol.categoryTransient) {
auto result = __indexSymbolNameHints.find(symbol);
return (result == __indexSymbolNameHints.end())? "" : result->second;
-
+
} else {
return "anonym(" + to_string(symbol.identifier) + ")";
}
}
-
+
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 76d83f3..ad8da19 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,227 +1,227 @@
#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/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <list>
namespace xreate {
typedef unsigned int ScopePacked;
struct SymbolPacked {
VID identifier;
ScopePacked scope;
bool categoryTransient = false;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
enum class DFGConnection {
STRONG, WEAK, PROTOTYPE
};
class IAnalysisData {
public:
void print(std::ostringstream& output) const;
virtual ~IAnalysisData(){};
};
class IQuery {
public:
virtual void init(ClaspLayer* clasp) = 0;
virtual ~IQuery() {}
};
enum class QueryId {
ContainersQuery,
ContextQuery,
PtrvalidQuery
};
namespace analysis{
class DFAGraph;
class CFAGraph;
}
class ClaspLayer {
friend class ContextRule;
//PROVIDERS:
public:
boost::scoped_ptr<xreate::analysis::DFAGraph> dataDFA;
void setDFAData(xreate::analysis::DFAGraph* graph);
boost::scoped_ptr<xreate::analysis::CFAGraph> dataCFA;
void setCFAData(xreate::analysis::CFAGraph* graph);
void addRawScript(std::string&& script);
private:
void involveImports();
//QUERIES
public:
IQuery* registerQuery(IQuery* query, const QueryId& id);
IQuery* getQuery(const QueryId& id);
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Symbol& atom);
typedef std::multimap<std::string, Gringo::Symbol>::const_iterator ModelIterator;
typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelFragment;
ModelFragment query(const std::string& atom);
size_t getScopesCount() const;
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
ScopePacked pack(CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol);
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
private:
std::map<QueryId, IQuery*> __queries;
std::multimap<std::string, Gringo::Symbol> __model;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<CodeScope*> __registryScopes;
//WARNINGS
//TODO move to separate provider/query
public:
void addRuleWarning(const RuleWarning &rule);
unsigned int registerWarning(std::string &&message);
private:
std::map<unsigned int, std::string> __warnings;
void printWarnings(std::ostream& out);
//DEFAULT
public:
AST *ast;
ClaspLayer();
void run();
private:
std::ostringstream __partTags;
std::ostringstream __partGeneral;
- bool handlerSolution(Gringo::Model const &model);
+ bool handleSolution(Gringo::Model const &model);
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Symbol& atom) {
switch (atom.type()) {
case Gringo::SymbolType::Str: return atom.string().c_str();
case Gringo::SymbolType::Fun: return atom.name().c_str();
default: break;
}
assert(false && "Inappropriate symbol type");
}
};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Symbol& atom) {
auto result = ClaspLayer::parse<unsigned int, unsigned int>(atom);
return SymbolPacked{std::get<0>(result), std::get<1>(result)};
}
};
template<>
struct ParseImplAtom<Gringo::Symbol> {
static Gringo::Symbol get(const Gringo::Symbol& atom) {
return atom;
}
};
template<>
struct ParseImplAtom<Expression> {
static Expression get(const Gringo::Symbol& atom) {
switch (atom.type()) {
case Gringo::SymbolType::Num: return Expression(atom.num());
case Gringo::SymbolType::Str: return Expression(std::string(atom.string().c_str()));
case Gringo::SymbolType::Fun:
{
//ID
if (!atom.args().size){
return Expression(std::string(atom.name().c_str()));
}
//FUNC
Expression result(Operator::CALL,{Expression(std::string(atom.name().c_str()))});
for (const Gringo::Symbol& 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::SymSpan::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::Symbol 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::SymSpan::iterator arg) {
}
};
template<class ...Types>
std::tuple<Types...>
ClaspLayer::parse(const Gringo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
}
#endif
diff --git a/cpp/src/compilation/advanced.cpp b/cpp/src/compilation/advanced.cpp
index db651c0..ba70f84 100644
--- a/cpp/src/compilation/advanced.cpp
+++ b/cpp/src/compilation/advanced.cpp
@@ -1,449 +1,449 @@
/*
* File: InstructionsAdvanced.cpp
* Author: pgess
*
* Created on June 26, 2016, 6:00 PM
*/
#include <compilation/transformations.h>
#include "compilation/advanced.h"
#include "compilation/containers.h"
#include "query/context.h"
#include "query/containers.h"
#include "query/ptrvalid.h"
#include "llvmlayer.h"
#include "ast.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
using namespace xreate::compilation;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
compilation::CodeScopeUnit* scope = context.scope; \
compilation::FunctionUnit* function = context.function;
Advanced::Advanced(compilation::Context ctx)
: context(ctx), tyNum (static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num)))))
{}
llvm::Value*
Advanced::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->__bindings[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);
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*
Advanced::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);
//TODO review array index compilation strategy
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*
Advanced::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);
// TODO review safety check: not null ptr
// SECTIONTAG validptr exception
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");
return nullptr;
}
llvm::Value*
Advanced::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* rangeBegin = it->begin();
llvm::Value* rangeEnd = 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];
TransformerSaturation* transformerSaturation = context.pass->transformations->get<TransformerSaturation>();
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
llvm::BasicBlock *blockBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "body", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
itLoop->addIncoming(rangeBegin, blockBeforeLoop);
// * loop body
llvm->builder.SetInsertPoint(blockBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * computing next iteration state
Value *itLoopNext = it->advance(itLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// * break checks, continue checks
//!! only after compiled Loop Body in order to fetch saturation expression
llvm->builder.SetInsertPoint(blockLoop);
if (transformerSaturation->exists())
{
transformerSaturation->inject(blockBeforeLoop, blockAfterLoop, context);
}
// * next iteration checks
Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
llvm->builder.CreateCondBr(condRange, blockBody, blockAfterLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
llvm::Value*
Advanced:: compileFoldInf(const Expression& fold, const std::string& hintRetVar){
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD_INF);
std::string accumName = fold.bindings[0];
llvm::Value* accumInit = scope->process(fold.getOperands()[0]);
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
llvm::BasicBlock *blockBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "body", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
TransformerSaturation* transformerSaturation = context.pass->transformations->get<TransformerSaturation>();
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
// * loop body
llvm->builder.SetInsertPoint(blockBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(accum, move(accumName));
Value* accumNext = unitLoop->compile();
// * computing next iteration state
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// * break checks, continue checks
assert(transformerSaturation->exists());
llvm->builder.SetInsertPoint(blockLoop);
transformerSaturation->inject(blockBeforeLoop, blockAfterLoop, context);
llvm->builder.CreateBr(blockBody);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
llvm::Value*
Advanced::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);
const Domain& 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();
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*
Advanced::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(tyResultType, 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
//TODO Switch: default variant no needed when all possible conditions are considered
llvm::Value*
Advanced::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);
+ assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
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*
Advanced::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*
Advanced::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);
}
diff --git a/cpp/src/compilation/latecontextcompiler.cpp b/cpp/src/compilation/latecontextcompiler.cpp
deleted file mode 100644
index 418b655..0000000
--- a/cpp/src/compilation/latecontextcompiler.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * LateContext.cpp
- *
- * Created on: Jan 8, 2016
- * Author: pgess
- */
-
-#include "query/context.h"
-#include <compilation/latecontextcompiler.h>
-#include "pass/compilepass.h"
-#include "llvmlayer.h"
-
-namespace xreate {
-
-LateContextCompiler::LateContextCompiler(const std::string& function, CompilePass* compilePass)
- : pass(compilePass)
-{}
-
-LateContextCompiler::~LateContextCompiler()
-{}
-
-llvm::Value*
-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*
-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, functionDomain->size(), "callee");
-
-
- //check runtime context
- 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(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*
-LateContextCompiler::compileArgument(const std::string& callee, ScopePacked scopeOuter){
- /*
- LLVMLayer* llvm = pass->man->llvm;
-
- std::unordered_set<size_t> indexContextStatic;
- 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* valueTrue = llvm::ConstantInt::get(tyBool, 1);
- llvm::Value* valueFalse = llvm::ConstantInt::get(tyBool, 0);
-
- for (const Expression& e: listContextStatic){
- 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);
- if (indexContextStatic.count(i))
- continue;
-
- 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/latecontextcompiler.h b/cpp/src/compilation/latecontextcompiler.h
deleted file mode 100644
index e3f6a2e..0000000
--- a/cpp/src/compilation/latecontextcompiler.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * LateContext.h
- *
- * Created on: Jan 8, 2016
- * Author: pgess
- */
-
-#ifndef SRC_COMPILATION_LATECONTEXTCOMPILER_H_
-#define SRC_COMPILATION_LATECONTEXTCOMPILER_H_
-
-#include "ast.h"
-
-namespace llvm {
- class Value;
- class Function;
-}
-
-namespace xreate {
-typedef unsigned int ScopePacked;
-
-class CompilePass;
-
-//SECTIONTAG late-context compilation logic wrt late context
-
-class LateContextCompiler{
-
-public:
- 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;
-
- llvm::Value* raw = nullptr;
-
-private:
- std::string functionName;
- CompilePass* pass;
-};
-
-} /* namespace xreate */
-
-#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..7008044
--- /dev/null
+++ b/cpp/src/compilation/latecontextcompiler2.cpp
@@ -0,0 +1,193 @@
+/*
+ * LateContextCompiler2.cpp
+ *
+ * Created on: 10 февр. 2016
+ * Author: pgess
+ */
+
+//TOTEST default variants - do not enable specialization context in order to check default variant invocation
+
+#include "latecontextcompiler2.h"
+#include "llvmlayer.h"
+#include "pass/compilepass.h"
+#include "query/context.h"
+#include <iostream>
+
+using namespace std;
+
+namespace xreate {
+
+const string topicSpecializationAtom = "specialization";
+const string topicDependencyAtom = "dependency";
+
+typedef ExpressionSerialization<RequirementIntegralCode>::Code DomainId;
+typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
+
+//TODO implement variantDefault;
+llvm::Value* compileDecisionSelector(llvm::IRBuilder<>& builder, llvm::Value* selector, std::vector<llvm::Value*> vectorVariants, llvm::Value* variantDefault=nullptr){
+ assert(vectorVariants.size()>0);
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ llvm::Type* tyElement = vectorVariants[0]->getType();
+ llvm::Type* tyVariants = llvm::VectorType::get(tyElement, vectorVariants.size());
+ llvm::Value* vectorRaw = llvm::ConstantVector::getNullValue(tyVariants);
+
+
+ for(DomainId i=0; i<vectorVariants.size(); ++i){
+ vectorRaw = builder.CreateInsertElement(vectorRaw, vectorVariants[i], llvm::ConstantInt::get(ty32, i));
+ }
+
+ return builder.CreateExtractElement(vectorRaw, selector);
+}
+
+LateContextCompiler2::LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p)
+ : function(f), pass(p){
+
+ ContextQuery* context = pass->queryContext;
+ __sizeOfDemand = context->getFunctionDemand(function->function->getName()).size();
+}
+
+llvm::Value*
+LateContextCompiler2::findFunction(const std::string& calleeName, llvm::Function* specializationDefault, ScopePacked scopeCaller){
+ const string& functionName = function->function->getName();
+ ContextQuery* context = pass->queryContext;
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+
+ const FunctionDemand& demand = context->getFunctionDemand(functionName);
+ const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
+
+ //independent decision:
+ Expression topic(Operator::CALL, {(Atom<Identifier_t>(string(topicSpecializationAtom))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
+ assert(demand.right.count(topic) && "Can't determine specialization for the function");
+ size_t topicId = demand.right.at(topic);
+ llvm::Value* topicDecisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
+
+ const Domain& specializationsDomain= context->getTopicDomain(topic);
+
+ std::vector<llvm::Function*> vectorVariants;
+ vectorVariants.reserve(specializationsDomain.size());
+ for (const ManagedFnPtr& f: specializations){
+ if (!f->guardContext.isValid()) continue;
+ const auto& variantId = specializationsDomain.getIdOptional(f->guardContext);
+ if (variantId){
+ if (vectorVariants.size() < *variantId + 1) {
+ vectorVariants.resize(*variantId + 1);
+ }
+
+ vectorVariants[*variantId] = pass->getFunctionUnit(f)->compile();
+ }
+ }
+
+ return compileDecisionSelectorAsSwitch(topicDecisionRaw, vectorVariants, specializationDefault);
+}
+
+llvm::Value*
+LateContextCompiler2::compileContextArgument(const std::string& callee, ScopePacked scopeCaller){
+ const std::string& atomDependentDecision = Config::get("clasp.context.decisions.dependent");
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ ContextQuery* context = pass->queryContext;
+
+ const string& functionName = function->function->getName();
+ const Decisions& dictStaticDecisions = context->getFinalDecisions(scopeCaller);
+
+ const FunctionDemand& demandCallee = context->getFunctionDemand(callee);
+ const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
+
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, demandCallee.size());
+
+ //builder.CreateAlloca(tyDemand, llvm::ConstantInt::get(ty32, 1));
+ llvm::Value* res = llvm::ConstantArray::getNullValue(tyDemand);
+
+ for (size_t i=0, size = demandCallee.size(); i<size; ++i){
+ const Expression& topic = demandCallee.left.at(i);
+ llvm::Value* decisionRaw;
+
+ if (demandSelf.right.count(topic)){
+ //TOTEST decision propagation
+ //propagate decision
+ const size_t& topicId = demandSelf.right.at(topic);
+ decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
+
+ } else if (dictStaticDecisions.count(topic)){
+ //static final decision:
+ const Expression& decision = dictStaticDecisions.at(topic);
+ const Domain& domainOfTopic = context->getTopicDomain(topic);
+ const DomainId& decisionCode = domainOfTopic.getId(decision);
+ decisionRaw = llvm::ConstantInt::get(ty32, decisionCode);
+
+ } else {
+ //dependent decision
+ decisionRaw = compileDependentDecision(topic, scopeCaller);
+ }
+
+ res = builder.CreateInsertValue(res, decisionRaw, llvm::ArrayRef<unsigned>{(unsigned) i});
+ }
+
+ return res;
+}
+
+llvm::Value*
+LateContextCompiler2::compileDependentDecision(const Expression& topic, ScopePacked scopeCaller){
+ const string& functionName = function->function->getName();
+ ContextQuery* context = pass->queryContext;
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
+ const Expression topicDependency = Expression(Operator::CALL, {Atom<Identifier_t>(string(topicDependencyAtom)), topic, Atom<Number_t>(scopeCaller)});
+
+ const Domain& demandOfTopic = context->getTopicDomain(topic);
+ const Domain& domainOfTopicDependency = context->getTopicDomain(topicDependency);
+
+ //dependent decision
+ vector<llvm::Value*> vectorDecisions(domainOfTopicDependency.size(), llvm::UndefValue::get(ty32));
+ for (const std::pair<Expression, Expression>& entry: context->getDependentDecision(scopeCaller,topic)){
+ vectorDecisions[domainOfTopicDependency.getId(entry.first)]= llvm::ConstantInt::get(ty32, demandOfTopic.getId(entry.second));
+ }
+
+ size_t topicDependencyId = demandSelf.right.at(topicDependency);
+ llvm::Value* decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicDependencyId});
+
+ auto result = compileDecisionSelector(pass->man->llvm->builder, decisionRaw, vectorDecisions);
+
+ return result;
+}
+
+
+
+llvm::Value*
+LateContextCompiler2::compileDecisionSelectorAsSwitch(llvm::Value* selector, std::vector<llvm::Function*> vectorVariants, llvm::Function* variantDefault){
+ llvm::IRBuilder<>& builder = pass->man->llvm->builder;
+ llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ llvm::BasicBlock* blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", this->function->raw);
+ llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "VariantDeterminationEnd", this->function->raw);
+
+ llvm::SwitchInst* instrSwitch = builder.CreateSwitch(selector, blockDefault, vectorVariants.size());
+
+ builder.SetInsertPoint(blockEpilog);
+ llvm::PHINode *result = builder.CreatePHI(variantDefault->getType(), vectorVariants.size(), "callee");
+
+ for (size_t i=0; i<vectorVariants.size(); ++i){
+ llvm::BasicBlock* blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "", this->function->raw);
+ builder.SetInsertPoint(blockCase);
+ builder.CreateBr(blockEpilog);
+ result->addIncoming(vectorVariants[i], blockCase);
+ instrSwitch->addCase(llvm::ConstantInt::get(ty32, i), blockCase);
+ }
+
+ builder.SetInsertPoint(blockDefault);
+ builder.CreateBr(blockEpilog);
+ result->addIncoming(variantDefault, blockDefault);
+
+ builder.SetInsertPoint(blockEpilog);
+ return result;
+}
+
+size_t
+LateContextCompiler2::getFunctionDemandSize() const {
+ return __sizeOfDemand;
+}
+
+} /* namespace xreate */
diff --git a/cpp/src/compilation/latecontextcompiler2.h b/cpp/src/compilation/latecontextcompiler2.h
new file mode 100644
index 0000000..abb12e1
--- /dev/null
+++ b/cpp/src/compilation/latecontextcompiler2.h
@@ -0,0 +1,51 @@
+/*
+ * LateContextCompiler2.h
+ *
+ * Created on: 10 февр. 2016
+ * Author: pgess
+ */
+
+//TOTEST compile several context arguments
+#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* rawContextArgument = nullptr;
+
+ LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p);
+ llvm::Value* findFunction(const std::string& calleeName, llvm::Function* specializationDefault, ScopePacked scopeCaller);
+ llvm::Value* compileContextArgument(const std::string& callee, ScopePacked scopeCaller);
+ size_t getFunctionDemandSize() const;
+
+private:
+ //boost::bimap<size_t, std::string> __decisions;
+ //std::vector<Domain> __scheme;
+
+ compilation::FunctionUnit* function;
+ CompilePass* pass;
+ size_t __sizeOfDemand;
+
+ llvm::Value* compileDependentDecision(const Expression& topic, ScopePacked scopeCaller);
+ llvm::Value* compileDecisionSelectorAsSwitch(llvm::Value* selector, std::vector<llvm::Function*> vectorVariants, llvm::Function* variantDefault);
+};
+} /* namespace xreate */
+
+#endif /* LATECONTEXTCOMPILER2_H_ */
\ No newline at end of file
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index fceda31..90c48fb 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,354 +1,447 @@
/*
* File: targetinterpretation.cpp
* Author: pgess
*
* Created on June 29, 2016, 6:45 PM
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
+#include "llvmlayer.h"
+#include <boost/scoped_ptr.hpp>
+#include <iostream>
using namespace std;
namespace xreate{ namespace compilation {
const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
//Expression
//InterpretationScope::compile(const Expression& expression){}
CodeScope*
InterpretationScope::processOperatorIf(const Expression& expression){
const Expression& exprCondition = process(expression.getOperands()[0]);
if (exprCondition == EXPRESSION_TRUE){
return expression.blocks.front();
}
return expression.blocks.back();
}
CodeScope*
InterpretationScope::processOperatorSwitch(const Expression& expression) {
const Expression& exprCondition = process(expression.operands[0]);
bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT;
//TODO check that one and only one case variant is appropriate
for (size_t size = expression.operands.size(), i= flagHasDefault? 2: 1; i<size; ++i){
const Expression& exprCase = process(expression.operands[i]);
if (function->getScope(exprCase.blocks.front())->processScope() == exprCondition){
return exprCase.blocks.back();
}
}
if (flagHasDefault){
const Expression& exprCaseDefault = expression.operands[1];
return exprCaseDefault.blocks.front();
}
assert(false && "Switch has no appropriate variant");
return nullptr;
}
llvm::Value*
InterpretationScope::compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context){
switch(op){
case IF_INTERPRET_CONDITION: {
CodeScope* scopeResult = processOperatorIf(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_INTERPRET_CONDITION:{
CodeScope* scopeResult = processOperatorSwitch(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case FOLD_INTERPRET_INPUT: {
//initialization
const Expression& exprInput = process(expression.getOperands()[0]);
assert(exprInput.op == Operator::LIST);
CodeScope* scopeBody = expression.blocks.front();
const string& nameEl = expression.bindings[0];
const Symbol& symbolEl = scopeBody->findSymbol(nameEl);
const std::string& idAccum = expression.bindings[1];
llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
compilation::CodeScopeUnit* unitBody = context.function->getScopeUnit(scopeBody);
InterpretationScope* intrBody = function->getScope(scopeBody);
const std::vector<Expression> elementsInput= exprInput.getOperands();
for (size_t i=0; i<elementsInput.size(); ++i){
Expression exprElement = elementsInput[i];
unitBody->reset();
- intrBody->bindArg(exprElement, nameEl);
+ intrBody->overrideBinding(exprElement, nameEl);
unitBody->overrideDeclaration(symbolEl, move(exprElement));
unitBody->bindArg(rawAccum, string(idAccum));
rawAccum = unitBody->compile();
}
return rawAccum;
}
+ case CALL_INTERPRET_PARTIAL: {
+ const std::string &calleeName = expression.getValueString();
+ CodeScopeUnit* scopeUnitSelf = context.scope;
+ ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName);
+ const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee);
+ std::vector<llvm::Value *> argsActual;
+ PIFSignature sig;
+ sig.declaration = callee;
+
+ for(size_t no=0, size = expression.operands.size(); no < size; ++no){
+ const Expression& op = expression.operands[no];
+
+ if (calleeData.signature.at(no) == INTR_ONLY){
+ sig.bindings.push_back(process(op));
+ continue;
+ }
+
+ argsActual.push_back(scopeUnitSelf->process(op));
+ }
+
+ TargetInterpretation* man = dynamic_cast<TargetInterpretation*>(this->function->man);
+ PIFunction* pifunction = man->getFunction(move(sig));
+
+ llvm::Function* raw = pifunction->compile();
+ boost::scoped_ptr<CallStatementRaw> statement(new CallStatementRaw(raw, man->pass->man->llvm));
+ return (*statement)(move(argsActual));
+ }
+
default: break;
}
assert(false&& "Unknown hybrid operator");
return nullptr;
}
llvm::Value*
InterpretationScope::compile(const Expression& expression, const Context& context){
const InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE){
return compileHybrid(data.op, expression, context);
}
Expression result = process(expression);
return context.scope->processLowlevel(result);
}
Expression
InterpretationScope::process(const Expression& expression){
switch (expression.__state){
case Expression::VARIANT:
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:{
const std::string &ident = expression.getValueString();
Symbol s = scope->findSymbol(ident);
return Parent::processSymbol(s);
}
case Expression::COMPOUND:
break;
default: assert(false);
}
switch (expression.op) {
case Operator::EQU: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_TRUE;
return EXPRESSION_FALSE;
}
case Operator::NE: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_FALSE;
return EXPRESSION_TRUE;
}
case Operator::LOGIC_AND: {
assert(expression.operands.size() == 1);
return process (expression.operands[0]);
}
// case Operator::LOGIC_OR:
case Operator::CALL: {
const std::string &fnName = expression.getValueString();
ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
InterpretatonFunction* fnUnit = this->function->man->getFunction(fnAst);
vector<Expression> args;
args.reserve(expression.getOperands().size());
for(size_t i=0, size = expression.getOperands().size(); i<size; ++i) {
args.push_back(process(expression.getOperands()[i]));
}
return fnUnit->process(args);
}
case Operator::IF:{
CodeScope* scopeResult = processOperatorIf(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH: {
CodeScope* scopeResult = processOperatorSwitch(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::INDEX: {
const Expression& exprKey = process(expression.operands[0]);
const Expression& exprData = processSymbol(scope->findSymbol(expression.getValueString()));
if (exprKey.__state == Expression::STRING){
const string& key = exprKey.getValueString();
assert(exprData.__indexBindings.count(key));
return exprData.operands[exprData.__indexBindings.at(key)];
}
if (exprKey.__state == Expression::NUMBER){
int key = exprKey.getValueDouble();
return exprData.operands[key];
}
assert(false);
}
case Operator::FOLD: {
const Expression& exprInput = process(expression.getOperands()[0]);
const Expression& exprInit = process(expression.getOperands()[1]);
const std::string& argEl = expression.bindings[0];
const std::string& argAccum = expression.bindings[1];
InterpretationScope* body = function->getScope(expression.blocks.front());
Expression accum = exprInit;
for(size_t size=exprInput.getOperands().size(), i=0; i<size; ++i){
- body->bindArg(exprInput.getOperands()[i], argEl);
- body->bindArg(accum, argAccum);
+ body->overrideBinding(exprInput.getOperands()[i], argEl);
+ body->overrideBinding(accum, argAccum);
accum = body->processScope();
}
return accum;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
-InterpretatonFunction::InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
- : Function<TargetInterpretation>(function, target)
-{}
+InterpretatonFunction*
+TargetInterpretation::getFunction(FunctionUnit* unit){
+ if (__dictFunctionsByUnit.count(unit)) {
+ return __dictFunctionsByUnit.at(unit);
+ }
-Expression
-InterpretatonFunction::process(const std::vector<Expression>& args){
- InterpretationScope* body = getScope(__function->__entry);
+ InterpretatonFunction* f = new InterpretatonFunction(unit->function, this);
+ __dictFunctionsByUnit.emplace(unit, f);
+ assert(__functions.emplace(unit->function.id(), f).second);
- for(size_t i=0, size = args.size(); i<size; ++i) {
- body->bindArg(args.at(i), string(body->scope->__bindings.at(i)));
+ return f;
+}
+
+PIFunction*
+TargetInterpretation::getFunction(PIFSignature&& sig){
+
+ auto f = __pifunctions.find<PIFSignature>(sig);
+ if (f != __pifunctions.end()){
+ return *f;
}
- return body->processScope();
-}
+ PIFunction* result = new PIFunction(move(sig), __pifunctions.size(), this);
+ __pifunctions.insert(result);
+ assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
-InterpretatonFunction*
-TargetInterpretation::getFunction(const PIFSignature& sig){
- return __functions.find(sig);
+ return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c){
- return this->getFunction(c.function->function)->getScope(c.scope->scope);
+ return this->getFunction(c.function)->getScope(c.scope->scope);
}
llvm::Value*
TargetInterpretation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
return raw;
}
Expression
TargetInterpretation::transform(const Expression& expression, const Context& ctx){
return transformContext(ctx)->process(expression);
}
llvm::Value*
TargetInterpretation::compile(const Expression& expression, const Context& ctx){
return transformContext(ctx)->compile(expression, ctx);
}
bool
TargetInterpretation::isAcceptable(const Expression& expression){
- const InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression, {BOTH, NONE});
+ const InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression, {ANY, NONE});
return (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
}
-}}
-
- //Partial function interpretation
-llvm::Value*
-InterpretationScope::compilePartialFnCall(const Expression& expression, const Context& context){
- const std::string &fnName = expression.getValueString();
- ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
- context.pass->getFunctionUnit(fnAst)
-
- intrBody->bindArg(exprElement, nameEl);
- unitBody->overrideDeclaration(symbolEl, move(exprElement));
-}
+InterpretatonFunction::InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
+ : Function<TargetInterpretation>(function, target)
+{}
-class PartialInterpretationScopeDecorator(){
- void compile(){
+Expression
+InterpretatonFunction::process(const std::vector<Expression>& args){
+ InterpretationScope* body = getScope(__function->__entry);
+ for(size_t i=0, size = args.size(); i<size; ++i) {
+ body->overrideBinding(args.at(i), string(body->scope->__bindings.at(i)));
}
- void findFunction(){
+ return body->processScope();
+}
- }
-};
+// Partial function interpretation
+
+typedef BasicFunctionDecorator PIFunctionUnitParent;
+class PIFunctionUnit: public PIFunctionUnitParent{
+public:
-template<class Parent>
-class PartialInterpretationFunctionDecorator: public Parent{
+ PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
+ : PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id)
+ {}
protected:
- void recognizeArguments(){
- argsReal.reserve(entry->__bindings.size());
+ std::vector<llvm::Type*> prepareArguments(){
+ LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm;
+ AST* ast = PIFunctionUnitParent::pass->man->root;
+ CodeScope* entry = PIFunctionUnitParent::function->__entry;
+ std::vector<llvm::Type*> signature;
- for(size_t no=0, size=entry->__bindings.size(); no < size; ++no){
- const std::string& argName = entry->__bindings[no];
- const Expression& arg = entry->findDeclaration(entry->findSymbol(argName));
+ for(size_t no: argumentsActual){
+ Symbol arg = entry->findSymbol(entry->__bindings[no]);
- InterpretationResolution res = recognizeTags(arg.tags);
- if (res != INTR_ONLY){
- argsReal.push_back(arg);
- }
+ signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations[arg.identifier].type)));
}
+
+ return signature;
}
- std::vector<llvm::Type*> prepareArguments(){
- std::vector<llvm::Type*> signature;
+ llvm::Function::arg_iterator prepareBindings(){
+ CodeScope* entry = PIFunctionUnitParent::function->__entry;
+ CodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
- for(size_t no=0, size=argsReal.size(); no < size; ++no){
- signature.push_back(llvm->toLLVMType(ast->expandType(argsReal[no].type)));
+ for(size_t no: argumentsActual){
+ Symbol arg = entry->findSymbol(entry->__bindings[no]);
+
+ entryCompilation->__rawVars[arg.identifier] = &*fargsI;
+ fargsI->setName(entry->__bindings[no]);
+ ++fargsI;
}
+
+ return fargsI;
}
- void prepareBindings(){
- // bindings from argsReal
+ virtual std::string prepareName(){
+ return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
}
private:
- std::vector<Expression> argsReal;
+ std::set<size_t> argumentsActual;
+ size_t __id;
};
-template<class Parent>
-class PartialInterpretationCallStatement: public Parent {
- PartialInterpretationCallStatement(){
+PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
+ : InterpretatonFunction(sig.declaration, target), signatureInstance(move(sig))
+{
+ const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration);
+
+ std::set<size_t> argumentsActual;
+ for (size_t no=0, size=functionData.signature.size(); no < size; ++no){
+ if (functionData.signature.at(no) != INTR_ONLY){
+ argumentsActual.insert(no);
+ }
+ }
+
+ functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass);
+ CodeScope* entry = signatureInstance.declaration->__entry;
+ CodeScopeUnit* entryUnit = functionUnit->getEntry();
+ InterpretationScope* entryIntrp = InterpretatonFunction::getScope(entry);
+ for(size_t no=0, sigNo=0, size = entry->__bindings.size(); no < size; ++no){
+ if (functionData.signature.at(no) == INTR_ONLY){
+ entryIntrp->overrideBinding(signatureInstance.bindings[sigNo], entry->__bindings[no]);
+ entryUnit->overrideDeclaration(entry->findSymbol(entry->__bindings[no]), Expression(signatureInstance.bindings[sigNo]));
+ ++sigNo;
+ }
}
-}
\ No newline at end of file
+}
+
+llvm::Function*
+PIFunction::compile(){
+ llvm::Function* raw = functionUnit->compile();
+
+ return raw;
+}
+
+bool operator<(const PIFSignature& lhs, const PIFSignature& rhs){
+ if (lhs.declaration.id() != rhs.declaration.id()) {
+ return lhs.declaration.id() < rhs.declaration.id();
+ }
+
+ return lhs.bindings < rhs.bindings;
+}
+
+bool operator<(const PIFSignature& lhs, PIFunction* const rhs){
+ return lhs < rhs->signatureInstance;
+}
+
+bool operator<(PIFunction* const lhs, const PIFSignature& rhs){
+ return lhs->signatureInstance < rhs;
+}
+
+}}
+
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 94c44d8..2d7444e 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,100 +1,117 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/*
* File: targetstatic.h
* Author: pgess
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H
#include "ast.h"
#include "compilation/targets.h"
#include "transformations.h"
#include "pass/interpretationpass.h"
namespace xreate{ namespace compilation {
class TargetInterpretation;
class InterpretationScope;
class InterpretatonFunction;
template <>
struct TargetInfo<TargetInterpretation> {
typedef Expression Result;
typedef InterpretationScope Scope;
typedef InterpretatonFunction Function;
};
template<>
struct TransformerInfo<TargetInterpretation> {
static const int id = 1;
};
class InterpretationScope: public Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(CodeScope* scope, Function<TargetInterpretation>* f): Parent(scope, f) {}
Expression process(const Expression& expression) override;
llvm::Value* compile(const Expression& expression, const Context& context);
private:
llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context);
- llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
+ //llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
-
};
class InterpretatonFunction: public Function<TargetInterpretation>{
- public:
- PIFSignature signature;
-
- InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target);
- Expression process(const std::vector<Expression>& args);
+public:
+ InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target);
+ Expression process(const std::vector<Expression>& args);
};
-/*
+/*
* Partially interpreted function signature
*/
struct PIFSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
-class TargetInterpretation: public Transformer, public Target<TargetInterpretation>{
+class PIFunctionUnit;
+
+class PIFunction: public InterpretatonFunction{
+public:
+ PIFunctionUnit* functionUnit;
+ PIFSignature signatureInstance;
+
+ PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
+ llvm::Function* compile();
+};
+
+bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
+bool operator<(PIFunction* const lhs, const PIFSignature& rhs);
+
+class TargetInterpretation: public Target<TargetInterpretation>, public Transformer{
public:
- TargetInterpretation(AST* root): Target<TargetInterpretation>(root){}
+ TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}
//transformer:
public:
virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
virtual Expression transform(const Expression& expression, const Context& ctx) override;
virtual bool isAcceptable(const Expression& expression) override;
//target:
public:
- InterpretatonFunction* getFunction(const ManagedFnPtr& function);
+ InterpretatonFunction* getFunction(FunctionUnit* unit);
+ PIFunction* getFunction(PIFSignature&& sig);
+
private:
- std::set<InterpretationFunction*> __functions;
+ std::set<PIFunction*, std::less<>> __pifunctions;
+ std::map<FunctionUnit*, InterpretatonFunction*> __dictFunctionsByUnit;
//self:
public:
+ CompilePass* pass;
llvm::Value* compile(const Expression& expression, const Context& ctx);
private:
InterpretationScope* transformContext(const Context& c);
};
+
+
}}
#endif /* TARGETSTATIC_H */
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
index fb10bec..b1821e3 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,146 +1,156 @@
/*
* File: targetabstract.h
* Author: pgess
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETABSTRACT_H
#define TARGETABSTRACT_H
#include "ast.h"
#include <boost/optional.hpp>
#include <map>
namespace xreate{ namespace compilation {
template <typename ConcreteTarget>
struct TargetInfo{
//typedef Result
//typedef Function
//typedef Scope
};
template<typename ConcreteTarget>
class Function;
template<typename ConcreteTarget>
class Target;
template<typename ConcreteTarget>
class Scope{
public:
CodeScope* scope;
typename TargetInfo<ConcreteTarget>::Result
processSymbol(const Symbol& s){
CodeScope* scope = s.scope;
typename TargetInfo<ConcreteTarget>::Scope* self = function->getScope(scope);
if (self->__bindings.count(s.identifier)) {
return self->__bindings[s.identifier];
}
const Expression& declaration = CodeScope::findDeclaration(s);
if (!declaration.isDefined()){
assert(false); //for bindings there should be result already
}
return self->__bindings[s.identifier] = self->process(declaration);
}
typename TargetInfo<ConcreteTarget>::Result
processScope() {
if (raw) return *raw;
- raw = process(scope->__body);
+ raw = process(scope->getBody());
return *raw;
}
+// typename TargetInfo<ConcreteTarget>::Result
+// processFunction(typename TargetInfo<ConcreteTarget>::Function* fnRemote, const std::vector<typename TargetInfo<ConcreteTarget>::Result>& args){
+// Scope<ConcreteTarget> scopeRemote = fnRemote->getScope(fnRemote->__function->__entry);
+//
+// if (scopeRemote->raw){
+// return scopeRemote->raw;
+// }
+//
+// return fnRemote->process(args);
+// }
+
virtual typename TargetInfo<ConcreteTarget>::Result
process(const Expression& expression)=0;
Scope(CodeScope* codeScope, Function<ConcreteTarget>* f)
: scope(codeScope), function(f) {}
virtual ~Scope(){}
void
- bindArg(typename TargetInfo<ConcreteTarget>::Result arg, const std::string& name){
+ overrideBinding(typename TargetInfo<ConcreteTarget>::Result arg, const std::string& name){
assert(scope->__identifiers.count(name));
VID id = scope->__identifiers.at(name);
__bindings[id] = arg;
//reset the result if any:
raw.reset();
}
protected:
- Function<ConcreteTarget>* function;
+ Function<ConcreteTarget>* function=0;
std::map<VID, typename TargetInfo<ConcreteTarget>::Result> __bindings;
typename boost::optional<typename TargetInfo<ConcreteTarget>::Result> raw;
//ResultType findFunction(const std::string& callee);
};
template<typename ConcreteTarget>
class Function{
typedef typename TargetInfo<ConcreteTarget>::Result Result;
public:
Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
: man(target), __function(function) {}
typename TargetInfo<ConcreteTarget>::Scope*
getScope(CodeScope* scope){
if (!__scopes.count(scope)){
typename TargetInfo<ConcreteTarget>::Scope* unit = new typename TargetInfo<ConcreteTarget>::Scope(scope, this);
__scopes.emplace(scope, std::unique_ptr<typename TargetInfo<ConcreteTarget>::Scope>(unit));
}
return __scopes.at(scope).get();
}
virtual Result
process(const std::vector<Result>& args)=0;
- Target<ConcreteTarget>* man;
-
-protected:
+ Target<ConcreteTarget>* man=0;
ManagedFnPtr __function;
-
+protected:
std::map<CodeScope*, std::unique_ptr<typename TargetInfo<ConcreteTarget>::Scope>> __scopes;
};
template<typename ConcreteTarget>
class Target {
typedef typename TargetInfo<ConcreteTarget>::Function ConcreteFunction;
public:
Target(AST* root): ast(root){}
ConcreteFunction*
getFunction(const ManagedFnPtr& function){
unsigned int id = function.id();
if (!__functions.count(id)){
ConcreteFunction* unit = new ConcreteFunction(function, this);
__functions.emplace(id, std::unique_ptr<ConcreteFunction>(unit));
return unit;
}
return __functions.at(id).get();
}
AST* ast;
+ virtual ~Target(){}
- private:
+ protected:
std::map<unsigned int, std::unique_ptr<ConcreteFunction>> __functions;
};
}}
#endif /* TARGETABSTRACT_H */
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index ec136fd..fc4e19f 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,35 +1,35 @@
#include "abstractpass.h"
#include "attachments.h"
#include "passmanager.h"
using namespace std;
namespace xreate {
template<>
void defaultValue<void>(){}
void AbstractPassBase::finish(){}
AbstractPassBase::AbstractPassBase(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const std::string& ident, PassContext context)
{
const Symbol& symbol = context.scope->findSymbol(ident);
if (__visitedSymbols.isCached(symbol))
return;
__visitedSymbols.setCachedValue(symbol);
const Expression& declaration = CodeScope::findDeclaration(symbol);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
process(declaration, context2, ident);
}
}
-}
+}
\ No newline at end of file
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 5595004..328a916 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,194 +1,201 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
#include "passmanager.h"
#include<iostream>
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
PassContext&& updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return std::move(context2);
}
~PassContext(){}
};
class AbstractPassBase {
public:
AbstractPassBase(PassManager* manager);
virtual void run()=0;
virtual void finish();
PassManager* man;
};
template<class Output>
Output defaultValue();
template<>
void defaultValue<void>();
template<class Output>
class SymbolCache: private std::map<Symbol, Output>{
public:
bool isCached(const Symbol& symbol){
return this->count(symbol);
}
Output setCachedValue(const Symbol& symbol, Output&& value){
- this->emplace(symbol, value);
+ (*this)[symbol] = value;
return value;
}
Output getCachedValue(const Symbol& symbol){
assert(this->count(symbol));
return this->at(symbol);
}
};
template<>
class SymbolCache<void>: private std::set<Symbol>{
public:
bool isCached(const Symbol& symbol){
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol& symbol){
this->insert(symbol);
}
void getCachedValue(const Symbol& symbol){
}
};
template<class Output>
class AbstractPass: public AbstractPassBase {
SymbolCache<Output> __visitedSymbols;
protected:
Output processSymbol(const std::string& ident, PassContext context){
const Symbol& symbol = context.scope->findSymbol(ident);
if (__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
const Expression& declaration = CodeScope::findDeclaration(symbol);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
Output&& result = process(declaration, context2, ident);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
SymbolCache<Output>& getSymbolCache(){
return __visitedSymbols;
}
-
public:
AbstractPass(PassManager* manager)
: AbstractPassBase(manager){}
- //NOTE implement processFnCall
- virtual void processFnCall(ManagedFnPtr function, PassContext context)
- {}
+ virtual Output processFnCall(ManagedFnPtr function, PassContext context){
+ return defaultValue<Output>();
+ }
virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context)
- {}
+ {}
virtual void process(ManagedRulePtr rule)
- {}
+ {}
- virtual Output process(ManagedFnPtr function){
- const Symbol& symbolFunction{0, function->getEntryScope()};
-
- if (__visitedSymbols.isCached(symbolFunction))
- return __visitedSymbols.getCachedValue(symbolFunction);
-
+ virtual Output process(ManagedFnPtr function)
+ {
PassContext context;
context.function = function;
-
+
return process(function->getEntryScope(), context);
- }
+ }
virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
context.scope = scope;
- return process(scope->__body, context);
+ return process(scope->getBody(), context);
}
virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
switch (expression.__state) {
case Expression::COMPOUND:
assert(expression.op != Operator::MAP || (expression.op == Operator::MAP && expression.blocks.size()));
//TODO there are discrepancies for SWITCH CASE scopes.case body parent scope differs from context.scope.
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
//
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL) {
const std::string &calleeName = expression.getValueString();
std::list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
if (callees.size() == 1 && callees.front()){
processFnCall(callees.front(), context);
} else {
for (const ManagedFnPtr& callee: callees){
processFnCallUncertain(callee, context);
}
}
}
break;
case Expression::IDENT:
assert(context.scope);
return processSymbol(expression.getValueString(), context);
default:
break;
}
return defaultValue<Output>();
}
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while (rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while (f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const std::string& ident, PassContext context);
}
#endif
+
+//PROCESS FUNCTION:
+// const Symbol& symbolFunction{0, function->getEntryScope()};
+//
+// if (__visitedSymbols.isCached(symbolFunction))
+// return __visitedSymbols.getCachedValue(symbolFunction);
+//
+// PassContext context;
+// context.function = function;
+//
+// Output&& result = process(function->getEntryScope(), context);
+// return __visitedSymbols.setCachedValue(symbolFunction, std::move(result));
\ No newline at end of file
diff --git a/cpp/src/pass/adhocpass.cpp b/cpp/src/pass/adhocpass.cpp
index ef9d1eb..65cde19 100644
--- a/cpp/src/pass/adhocpass.cpp
+++ b/cpp/src/pass/adhocpass.cpp
@@ -1,81 +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){
const ScopePacked scopeId = man->clasp->pack(entry);
const Domain& domain = queryContext->getContext(scopeId);
AdhocScheme* scheme = nullptr;
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();
+ std::string nameCase = blockComm->getBody().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/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 6c52cee..19129be 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,812 +1,827 @@
#include "compilepass.h"
#include "clasplayer.h"
-#include "llvmlayer.h"
#include <ast.h>
+#include "llvmlayer.h"
#include "query/containers.h"
#include "query/context.h"
#include "compilation/containers.h"
#include "compilation/transformations.h"
+#include "compilation/latecontextcompiler2.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
-//#include "compilation/targetinterpretation.h"
+#include "compilation/targetinterpretation.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace xreate;
using namespace xreate::compilation;
using namespace llvm;
//TODO use Scope<TargetLlvm>
//SECTIONTAG types/convert implementation
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissalow based on annotations)
namespace xreate {
llvm::Value*
doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder){
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 builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
}
if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
}
}
if (source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()){
return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
}
return source;
}
-CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
- : scope(codeScope), pass(compilePass), function(f)
-{}
+std::string
+BasicFunctionDecorator::prepareName(){
+ AST* ast = FunctionUnit::pass->man->root;
+
+ string name = ast->getFunctionVariants(FunctionUnit::function->__name).size() > 1?
+ FunctionUnit::function->__name + std::to_string(FunctionUnit::function.id()) :
+ FunctionUnit::function->__name;
+
+ return name;
+}
+
+std::vector<llvm::Type*>
+BasicFunctionDecorator::prepareArguments(){
+ LLVMLayer* llvm = FunctionUnit::pass->man->llvm;
+ AST* ast = FunctionUnit::pass->man->root;
+ CodeScope* entry = FunctionUnit::function->__entry;
+ std::vector<llvm::Type*> signature;
+
+ std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
+ [llvm, ast, entry](const std::string &arg)->llvm::Type* {
+ assert(entry->__identifiers.count(arg));
+
+ VID argid = entry->__identifiers.at(arg);
+ return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
+ });
+
+ return signature;
+}
+
+llvm::Type*
+BasicFunctionDecorator::prepareResult(){
+ LLVMLayer* llvm = FunctionUnit::pass->man->llvm;
+ AST* ast = FunctionUnit::pass->man->root;
+ CodeScope* entry = FunctionUnit::function->__entry;
+
+ return llvm->toLLVMType(ast->expandType(entry->__declarations[0].type));
+}
+
+llvm::Function::arg_iterator
+BasicFunctionDecorator::prepareBindings(){
+ CodeScope* entry = FunctionUnit::function->__entry;
+ CodeScopeUnit* entryCompilation = FunctionUnit::getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = FunctionUnit::raw->arg_begin();
+
+ for (std::string &arg : entry->__bindings) {
+ VID argid = entry->__identifiers[arg];
+
+ entryCompilation->__rawVars[argid] = &*fargsI;
+ fargsI->setName(arg);
+ ++fargsI;
+ }
+
+ return fargsI;
+}
+
+//SECTIONTAG late-context FunctionDecorator
+template<class Parent>
+class LateContextFunctionDecorator: public Parent{
+public:
+ LateContextFunctionDecorator(ManagedFnPtr f, CompilePass* p)
+ : Parent(f, p), contextCompiler(this, p)
+ {}
+
+protected:
+ std::vector<llvm::Type*> prepareArguments(){
+ std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
+
+ size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
+ if (sizeLateContextDemand) {
+ llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
+
+ arguments.push_back(tyDemand);
+ }
+
+ return arguments;
+ }
+ llvm::Function::arg_iterator prepareBindings(){
+ llvm::Function::arg_iterator fargsI = Parent::prepareBindings();
+
+ size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
+ if (sizeLateContextDemand){
+ fargsI->setName("latecontext");
+ contextCompiler.rawContextArgument = &*fargsI;
+ ++fargsI;
+ }
+
+ return fargsI;
+ }
-class CallStatement {
public:
- virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>&) = 0;
+ LateContextCompiler2 contextCompiler;
+
};
-class CallStatementRaw: public CallStatement{
+//SECTIONTAG adhoc FunctionDecorator
+template<class Parent>
+class AdhocFunctionDecorator: public Parent{
public:
- CallStatementRaw(llvm::Function* callee): __callee(callee) {}
+ AdhocFunctionDecorator(ManagedFnPtr f, CompilePass* p)
+ : Parent(f, p) {}
- llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
- auto argsFormal = __callee->args();
+protected:
+ llvm::Type* prepareResult(){
+ PassManager* man = Parent::pass->man;
+ CodeScope* entry = Parent::function->__entry;
+ LLVMLayer* llvm = Parent::pass->man->llvm;
+ AST* ast = Parent::pass->man->root;
+ AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(man->getPassById(PassId::AdhocPass));
- int pos=0;
- //SECTIONTAG types/convert function ret value
- for (auto argFormal = argsFormal.begin(); argFormal!=argsFormal.end(); ++argFormal, ++pos){
- args[pos] = doAutomaticTypeConversion(args[pos], argFormal->getType(), builder);
- }
+ if (! Parent::function->isPrefunction){
+ return Parent::prepareResult();
+ }
- return builder.CreateCall(__callee, args, hintDecl);
- }
+ adhocImplementation = adhocpass->determineForScope(entry);
+ return llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
+ }
+
+public:
+ AdhocScheme* adhocImplementation=nullptr;
-private:
- llvm::Function* __callee;
};
-//TASK implement inlining
+typedef LateContextFunctionDecorator<
+ AdhocFunctionDecorator<
+ BasicFunctionDecorator>> DefaultFunctionUnit;
+
+
+CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
+ : scope(codeScope), pass(compilePass), function(f)
+{}
+
+
+llvm::Value*
+CallStatementRaw::operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
+ llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
+
+ if (calleeInfo){
+ auto argsFormal = calleeInfo->args();
+
+ int pos=0;
+ //SECTIONTAG types/convert function ret value
+ for (auto argFormal = argsFormal.begin(); argFormal!=argsFormal.end(); ++argFormal, ++pos){
+ args[pos] = doAutomaticTypeConversion(args[pos], argFormal->getType(), llvm->builder);
+ }
+ }
+
+ return llvm->builder.CreateCall(__calleeTy, __callee, args, hintDecl);
+}
+
+//DEBT implement inlining
class CallStatementInline: public CallStatement{
public:
- CallStatementInline(FunctionUnit* caller, FunctionUnit* callee)
- : __caller(caller), __callee(callee) {}
+ CallStatementInline(FunctionUnit* caller, FunctionUnit* callee, LLVMLayer* l)
+ : __caller(caller), __callee(callee), llvm(l) {}
- llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl, llvm::IRBuilder<>& builder) {
+ llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//TOTEST inlining
// CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
// for(int i=0, size = args.size(); i<size; ++i) {
// entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
// }
//
//
// return entryCompilation->compile();
}
private:
FunctionUnit* __caller;
FunctionUnit* __callee;
+ LLVMLayer* llvm;
bool isInline(){
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
};
-template<class Parent>
-class CallStatementLateContext: public CallStatement{
- {
- if (specializations.size()< 2){
- return Parent...
- }
-
-
-
-
-
-
-
- }
-
-};
}
void
CodeScopeUnit::overrideDeclaration(const Symbol binding, Expression&& declaration){
function->getScopeUnit(binding.scope)->__declarationsOverriden.emplace(binding.identifier, move(declaration));
}
-class ScopeDecorator{
-
-};
-
//SECTIONTAG late-context find callee function
//TOTEST static late context decisions
//TOTEST dynamic late context decisions
CallStatement*
CodeScopeUnit::findFunction(const std::string& calleeName){
LLVMLayer* llvm = pass->man->llvm;
ClaspLayer* clasp = pass->man->clasp;
-
+ DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
ContextQuery* queryContext = pass->queryContext;
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
//if no specializations registered - check external function
if (specializations.size()==0){
llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
- return new CallStatementRaw(external);
+ return new CallStatementRaw(external, llvm);
}
//no decisions required
if (specializations.size()==1){
if (!specializations.front()->guardContext.isValid()) {
- return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile());
+ return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile(), llvm);
}
}
//TODO move dictSpecialization over to a separate function in order to perform cache, etc.
//prepare specializations dictionary
std::map<Expression, 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(guard, f).second && "Found several identical specializations");
}
//check static context
ScopePacked scopeCaller = clasp->pack(this->scope);
const string atomSpecialization = "specialization";
const Expression topicSpecialization(Operator::CALL, {(Atom<Identifier_t>(string(atomSpecialization))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
const Decisions& decisions = queryContext->getFinalDecisions(scopeCaller);
if (decisions.count(topicSpecialization)){
variant = dictSpecializations.at(decisions.at(topicSpecialization));
}
//TODO check only demand for this particular topic.
- size_t sizeDemand = this->function->contextCompiler.getFunctionDemandSize();
+ size_t sizeDemand = 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);
- }
+// if (calleeUnit->isInline()) {
+// return new CallStatementInline(function, calleeUnit);
+// }
- return new CallStatementRaw(calleeUnit->compile());
+ return new CallStatementRaw(calleeUnit->compile(), llvm);
}
//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, scopeCaller));
+ llvm::Value* resultFn = function->contextCompiler.findFunction(calleeName, functionVariantDefault, scopeCaller);
+ llvm::PointerType *resultPTy = cast<llvm::PointerType>(resultFn->getType());
+ llvm::FunctionType *resultFTy = cast<llvm::FunctionType>(resultPTy->getElementType());
+ return new CallStatementRaw(resultFn, resultFTy, llvm);
}
void
CodeScopeUnit::bindArg(llvm::Value* value, std::string&& alias)
{
//reset cached compiled value if any
raw = nullptr;
//ensure existing of an alias
assert(scope->__identifiers.count(alias));
//memorize new value for an alias
VID id = scope->__identifiers.at(alias);
__rawVars[id] = value;
}
llvm::Value*
CodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
Context ctx{this, this->function, this->pass};
-// if (pass->targetInterpretation->isAcceptable(expr)){
-// return pass->targetInterpretation->compile(expr, ctx);
-// }
+ if (pass->targetInterpretation->isAcceptable(expr)){
+ return pass->targetInterpretation->compile(expr, ctx);
+ }
llvm::Value* result = processLowlevel(expr, hintVarDecl);
if (pass->transformations->isAcceptable(expr)){
return pass->transformations->transform(expr, result, ctx);
}
return result;
}
llvm::Value*
CodeScopeUnit::processLowlevel(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;
xreate::compilation::Advanced instructions = xreate::compilation::Advanced({this, function, 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: case Operator::NE: case Operator::LSE:
case Operator::GTE:
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.builder);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
case Operator::SUB:
return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU:
if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
break;
case Operator::NE:
return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
break;
case Operator::CALL: {
assert(expr.__state == Expression::COMPOUND);
std::string nameCallee = expr.getValueString();
- unique_ptr<CallStatement> callee(findFunction(nameCallee));
+ shared_ptr<CallStatement> callee(findFunction(nameCallee));
//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);
+ //TASK a) refactor CALL/ADHOC/find function
//SECTIONTAG late-context propagation arg
size_t calleeDemandSize = pass->queryContext->getFunctionDemand(nameCallee).size();
if (calleeDemandSize){
+ DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
llvm::Value* argLateContext = function->contextCompiler.compileContextArgument(nameCallee, outerScopeId);
args.push_back(argLateContext);
}
- return (*callee)(move(args), DEFAULT("res_"+nameCallee), l.builder);
+ return (*callee)(move(args), DEFAULT("res_"+nameCallee));
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOOP_CONTEXT:
{
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, 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, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
case Operator::FOLD_INF:
{
return instructions.compileFoldInf(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 = CodeScope::findDeclaration(s).type;
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, DEFAULT(string("el_") + ident));
};
default:
assert(false);
}
};
//SECTIONTAG adhoc actual compilation
+ //TODO a) make sure that it's correct: function->adhocImplementation built for Entry scope and used in another scope
case Operator::ADHOC: {
- assert(function->adhocImplementation && "Adhoc implementation not found");
- string comm = expr.operands[0].getValueString();
+ DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
+ assert(function->adhocImplementation && "Adhoc implementation not found");
+ string comm = expr.operands[0].getValueString();
+
+ CodeScope* scope = function->adhocImplementation->getImplementationForCommand(comm);
+ CodeScopeUnit* unitScope = function->getScopeUnit(scope);
- CodeScope* scope = function->adhocImplementation->getImplementationForCommand(comm);
- CodeScopeUnit* unitScope = function->getScopeUnit(scope);
- return unitScope->compile();
+ //SECTIONTAG types/convert ADHOC ret convertation
+ llvm::Type* resultTy = l.toLLVMType( pass->man->root->expandType(function->adhocImplementation->getResultType()));
+ return doAutomaticTypeConversion(unitScope->compile(), resultTy, l.builder);
};
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(), 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*
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);
+ raw = process(scope->getBody());
return raw;
}
llvm::Value*
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];
}
//compilation transformations could override symbol declarations.
Expression declaration = CodeScope::findDeclaration(s);
if (!declaration.isDefined()){
if (self->__declarationsOverriden.count(s.identifier)){
declaration = self->__declarationsOverriden[s.identifier];
} else {
assert(false); //in case of bindings there should be raws already.
}
}
return self->__rawVars[s.identifier] = self->process(declaration, hintRetVar);
}
-//SECTIONTAG late-context FunctionDecorator
-template<class Parent>
-class LateContextFunctionDecorator: public Parent{
-
- LateContextFunctionDecorator(ManagedFnPtr f, CompilePass* p)
- : Parent(f, p), contextCompiler(this, p)
- {}
-
- std::vector<llvm::Type*> prepareArguments(){
- std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
-
- size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
- if (sizeLateContextDemand) {
- llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
- llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
-
- arguments.push_back(tyDemand);
- }
- return arguments;
- }
-
- void prepareBindings(){
- if (sizeLateContextDemand){
- fargsI->setName("latecontext");
- contextCompiler.rawContextArgument = &*fargsI;
- }
- }
-
-protected:
- LateContextCompiler2 contextCompiler;
-};
-
-//SECTIONTAG adhoc FunctionDecorator
-template<class Parent>
-class AdhocFunctionDecorator: public Parent{
-protected:
- llvm::Type* prepareResult(){
- if (! function->isPrefunction){
- return Parent::prepareResult();
- }
-
- AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(pass->man->getPassById(PassId::AdhocPass));
- adhocImplementation = adhocpass->determineForScope(entry);
-
- return llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
- }
-
-private:
- AdhocScheme* adhocImplementation=nullptr; //SECTIONTAG adhoc prefunc scheme declaration
-};
-
-template<class Decorator>
-class BasicFunctionDecorator: public Decorator{
-protected:
- std::string prepareName(){
- string name = ast->getFunctionVariants(function->__name).size() > 1?
- function->__name + std::to_string(function.id()) :
- function->__name;
-
- return name;
- }
-
- virtual std::vector<llvm::Type*> prepareArguments(){
- std::vector<llvm::Type*> signature;
- std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
- [this, llvm, ast, entry](const std::string &arg)->llvm::Type* {
- assert(entry->__identifiers.count(arg));
- VID argid = entry->__identifiers.at(arg);
- return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
- });
- return signature;
- }
-
- virtual llvm::Type* prepareResult(){
- return llvm->toLLVMType(ast->expandType(entry->__declarations[0].type));
- }
-
- virtual void prepareBindings(){
- CodeScope* entry = function->__entry;
-
- CodeScopeUnit* entryCompilation = getScopeUnit(entry);
- llvm::Function::arg_iterator fargsI = raw->arg_begin();
- for (std::string &arg : entry->__bindings) {
- VID argid = entry->__identifiers[arg];
-
- entryCompilation->__rawVars[argid] = &*fargsI;
- fargsI->setName(arg);
- ++fargsI;
- }
- }
-};
-typedef LateContextFunctionDecorator<
- AdhocFunctionDecorator<
- BasicFunctionDecorator<FunctionUnit>>> DefaultFunctionUnit;
llvm::Function*
FunctionUnit::compile(){
if (raw != nullptr) return raw;
-
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
- AST* ast = pass->man->root;
-
-
-
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareArguments();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
- llvm::Value* result = entryCompilation->compile(blockName);
+ llvm::Value* result =getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
builder.CreateRet(doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent){
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
CodeScopeUnit*
FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
scopes.emplace(scope, std::unique_ptr<CodeScopeUnit>(unit));
}
return scopes.at(scope).get();
}
CodeScopeUnit*
FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
CodeScopeUnit*
FunctionUnit::getScopeUnit(ManagedScpPtr scope){
return getScopeUnit(&*scope);
}
FunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function){
unsigned int id = function.id();
if (!functions.count(id)){
FunctionUnit* unit = new DefaultFunctionUnit(function, this);
functions.emplace(id, unit);
return unit;
}
- return functions.at(id).get();
+ return functions.at(id);
}
void
CompilePass::run(){
transformations = new Transformations(this);
transformations->registerTransformer(new TransformerSaturation(transformations));
- //targetInterpretation = new TargetInterpretation(this->man->root);
+ targetInterpretation = new TargetInterpretation(this->man->root, this);
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 54fb72d..416de88 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,120 +1,155 @@
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
-#include <compilation/latecontextcompiler2.h>
#include "abstractpass.h"
#include "llvm/IR/Function.h"
namespace xreate {
class AdhocScheme;
class ClaspLayer;
class ContextQuery;
- class CallStatement;
+ class LLVMLayer;
}
+//namespace llvm {
+// class Function;
+// class Value;
+// class Type;
+//}
+
namespace xreate {
class CompilePass;
namespace compilation {
class CodeScopeUnit;
class FunctionUnit;
class TargetInterpretation;
struct Context{
CodeScopeUnit* scope;
FunctionUnit* function;
CompilePass* pass;
};
+class CallStatement {
+public:
+ virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="") = 0;
+};
+
+class CallStatementRaw: public CallStatement{
+public:
+ CallStatementRaw(llvm::Function* callee, LLVMLayer* l)
+ : __callee(callee), __calleeTy(callee->getFunctionType()), llvm(l) {}
+ CallStatementRaw(llvm::Value* callee, llvm::FunctionType* ty, LLVMLayer* l)
+ : __callee(callee), __calleeTy(ty), llvm(l) {}
+ llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="");
+
+private:
+ llvm::Value* __callee;
+ llvm::FunctionType* __calleeTy;
+
+ LLVMLayer* llvm;
+};
+
class CodeScopeUnit {
public:
CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
void bindArg(llvm::Value* value, std::string&& alias);
void overrideDeclaration(const Symbol binding, Expression&& declaration);
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="");
llvm::Value* processLowlevel(const Expression& expr, const std::string& hintVarDecl="");
CodeScope* scope;
private:
CompilePass* pass;
llvm::Value* raw = nullptr;
FunctionUnit* function;
std::unordered_map<VID, Expression> __declarationsOverriden;
CallStatement* findFunction(const std::string& callee);
};
class IFunctionDecorator {
protected:
virtual std::string prepareName() = 0;
virtual std::vector<llvm::Type*> prepareArguments() = 0;
virtual llvm::Type* prepareResult() = 0;
- virtual void prepareBindings() = 0;
+ virtual llvm::Function::arg_iterator prepareBindings() = 0;
virtual ~IFunctionDecorator(){}
};
class FunctionUnit: public IFunctionDecorator{
public:
FunctionUnit(ManagedFnPtr f, CompilePass* p)
: function(f), pass(p) {}
llvm::Function* compile();
CodeScopeUnit* getEntry();
CodeScopeUnit* getScopeUnit(CodeScope* scope);
CodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
ManagedFnPtr function;
llvm::Function* raw = nullptr;
protected:
- std::string prepareName();
- std::vector<llvm::Type*> prepareArguments();
- llvm::Type* prepareResult();
+ CompilePass* pass=nullptr;
private:
- CompilePass* pass;
std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
};
+class BasicFunctionDecorator: public FunctionUnit{
+public:
+ BasicFunctionDecorator(ManagedFnPtr f, CompilePass* p)
+ : FunctionUnit(f, p) {}
+
+protected:
+ std::string prepareName();
+ virtual std::vector<llvm::Type*> prepareArguments();
+ virtual llvm::Type* prepareResult();
+ virtual llvm::Function::arg_iterator prepareBindings();
+};
+
class Transformations;
} // 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:
compilation::Transformations* transformations;
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
compilation::FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
void run() override;
llvm::Function* getEntryFunction();
static void prepareQueries(ClaspLayer* clasp);
private:
- std::map<unsigned int, compilation::FunctionUnit> functions;
+ //TODO free `functions` in destructor
+ std::map<unsigned int, compilation::FunctionUnit*> functions;
llvm::Function* entry = 0;
ContextQuery* queryContext;
compilation::TargetInterpretation* targetInterpretation;
};
}
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
index 2939d08..7a019e1 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,256 +1,240 @@
#include "pass/dfapass.h"
#include "analysis/dfagraph.h"
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
using namespace std;
using namespace xreate::analysis;
namespace xreate{
-
+
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, __context{new xreate::analysis::DFAGraph(manager->clasp)}
, clasp(manager->clasp)
{}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
const SymbolPacked& retFormal{0, clasp->pack(scope)};
__context.graph->addConnection(retFormal, retActual, DFGConnection::STRONG);
return retFormal;
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
ExpressionCache cache;
-
+
if (!decl.empty()){
cache.result = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
-
+
} else if (!expression.tags.empty()) {
cache.result = __context.graph->createAnonymousSymbol(clasp->pack(context.scope));
-
+
} else {
cache.result = SymbolTransient{{}, clasp->pack(context.scope)};
}
-
+
cache.operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
cache.operands.push_back(process(op, context));
}
-
+
cache.blocks.reserve(expression.blocks.size());
for (CodeScope* scope: expression.blocks) {
cache.blocks.push_back(process(scope, context));
}
-
- if (expression.__state != Expression::COMPOUND) {
- processElementaryOp(expression, context, cache, decl);
-
- } else {
+
+ if (expression.__state == Expression::COMPOUND) {
processCompoundOp(expression, context, cache, decl);
+
+ } else {
+ processElementaryOp(expression, context, cache, decl);
}
-
+
applyDependencies(expression, context, cache, decl);
applyStaticAnnotations(expression, context, cache, decl);
applySignatureAnnotations(expression, context, cache, decl);
applyInPlaceAnnotations(expression, context, cache, decl);
-
+
//TODO Null ad hoc DFG implementation
// if (expression.isNone()){
// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
// }
-
+
//non initialized(SymbolInvalid) value
-
+
return cache.result;
}
void
DFAPass::processElementaryOp(const Expression& expression, PassContext context, DFAPass::ExpressionCache& cache, const std::string& varDecl){
switch(expression.__state) {
case Expression::IDENT: {
std::string identifier = expression.getValueString();
-
+
SymbolNode nodeFrom = AbstractPass::process(expression, context, identifier);
if (SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result)){
__context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::STRONG);
+
+ } else {
+ // cache.result = nodeFrom;
}
-
+
break;
}
-
+
default: break;
}
}
void
DFAPass::processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl){
switch(expression.op) {
//apply calling relation
case Operator::CALL: {
const string &nameCalleeFunction = expression.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction = man->root->getFunctionVariants(nameCalleeFunction);
if (variantsCalleeFunction.size()!=1) return;
ManagedFnPtr function= variantsCalleeFunction.front();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
std::vector<SymbolNode>::iterator nodeActual = cache.operands.begin();
for (const std::string &identFormal: scopeRemote->__bindings) {
const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
__context.graph->addConnection(clasp->pack(symbolFormal, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK);
++nodeActual;
}
-
+
//TODO represent RET connection
break;
}
-
+
//apply PROTOTYPE relation
case Operator::MAP: {
SymbolNode nodeFrom= cache.operands.front();
SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
assert(nodeFromPacked);
-
+
SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result);
assert(nodeTo);
-
- __context.graph->addConnection(*nodeTo, *nodeFromPacked, DFGConnection::PROTOTYPE);
+
+ __context.graph->addConnection(*nodeTo, *nodeFromPacked, DFGConnection::PROTOTYPE);
break;
}
-
+
default: break;
}
}
void
DFAPass::applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
for (SymbolNode &op: cache.operands) {
__context.graph->addDependencyConnection(cache.result, op);
}
-
+
for (SymbolNode &block: cache.blocks) {
__context.graph->addDependencyConnection(cache.result, block);
}
-
+
switch(expression.__state) {
case Expression::IDENT: {
const string& identName = expression.getValueString();
-
+
SymbolNode identSymbol = clasp->pack(context.scope->findSymbol(identName), context.function->getName() + ":" + identName);
__context.graph->addDependencyConnection(cache.result, identSymbol);
}
-
+
default: break;
}
}
void
DFAPass::applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
-
+
switch(expression.__state) {
case Expression::NUMBER:
case Expression::STRING:
__context.graph->addAnnotation(cache.result, Expression(Atom<Identifier_t>("static")));
break;
-
+
default: break;
}
}
-
+
void
DFAPass::applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
if (__signatures.count(expression.op)) {
const Expression &scheme = __signatures.at(expression.op);
//TODO add possibility to specifi signature for a particular function
// if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
// string caption = expression.getValueString();
// operands.push_back(process(Expression(move(caption)), context, ""));
// }
std::vector<SymbolNode>::iterator arg = cache.operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
__context.graph->addAnnotation(*arg, Expression(*tag));
}
++arg; ++tag;
}
//TODO represent RET connection
// Expression retTag = *scheme.getOperands().begin();
// if (retTag.__state != Expression::INVALID) {
// __context.graph->addAnnotation(node, move(retTag));
// }
}
}
void
DFAPass::applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
// write down in-place expression tags:
for (pair<std::string, Expression> tag: expression.tags) {
__context.graph->addAnnotation(cache.result, Expression(tag.second));
}
}
void
DFAPass::run()
{
init();
return AbstractPass::run();
}
void
DFAPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
__signatures.emplace(scheme.op, scheme);
}
}
void DFAPass::finish()
{
man->clasp->setDFAData(move(__context.graph));
}
template<>
SymbolNode defaultValue(){return SymbolInvalid();};
}
-
-
-
-
-/*
-if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
- std::vector<Tag> tags;
- tags.reserve(symbT->tags.size());
-
- const std::string stmntRetTag = Config::get("clasp.ret.tag");
- std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
- [&stmntRetTag](const Expression& e) {
- Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
- return Tag{e, TagModifier::NONE};
- });
-
- clasp->cfagraph->addFunctionAnnotations(function->getName(), tags);
-}
-*/
\ No newline at end of file
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index 968efa4..b4d399e 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,334 +1,406 @@
/*
* File: interpretationpass.cpp
* Author: pgess
*
* Created on July 5, 2016, 5:21 PM
*/
#include "pass/interpretationpass.h"
#include "compilation/transformations.h"
#include <compilation/targetinterpretation.h>
#include "ast.h"
//DEBT implement InterpretationPass purely in clasp
//DEBT represent InterpretationPass as general type inference
using namespace std;
namespace xreate{
enum InterpretationQuery{QUERY_INTR_ONLY, QUERY_CMPL_ONLY};
template<>
InterpretationResolution
defaultValue<InterpretationResolution>(){
return CMPL_ONLY;
}
InterpretationResolution
unify(InterpretationResolution flag) {
return flag;
}
template<typename FLAG_A, typename FLAG_B, typename... FLAGS>
InterpretationResolution
unify(FLAG_A flagA, FLAG_B flagB, FLAGS... flags) {
- if (flagA== BOTH){
+ if (flagA== ANY){
return unify(flagB, flags...);
}
- if (flagB == BOTH) {
+ if (flagB == ANY) {
return unify(flagA, flags...);
}
assert(flagA == flagB);
return flagA;
}
namespace detail {
template<InterpretationQuery FLAG_REQUIRED>
bool checkConstraints(InterpretationResolution flag) {
return ( (flag==INTR_ONLY && FLAG_REQUIRED == QUERY_INTR_ONLY)
|| (flag==CMPL_ONLY && FLAG_REQUIRED == QUERY_CMPL_ONLY));
}
}
template<InterpretationQuery FLAG_REQUIRED>
bool checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag = flags.front();
return detail::checkConstraints<FLAG_REQUIRED>(flag);
}
template<InterpretationQuery FLAG_REQUIRED_A, InterpretationQuery FLAG_REQUIRED_B, InterpretationQuery... FLAGS>
bool checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag = flags.front();
flags.pop_back();
if (detail::checkConstraints<FLAG_REQUIRED_A>(flag)){
return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
}
return false;
}
-void
-setSpecializedOperator(const Expression& expression, const InterpretationOperator& op){
- if (Attachments::exists<Expression, InterpretationData>(expression)){
- InterpretationData& data = Attachments::get<Expression, InterpretationData>(expression);
- data.op = op;
-
- } else {
- Attachments::put<Expression, InterpretationData>(expression, {BOTH, op});
- }
+namespace details {
+ InterpretationResolution
+ recognizeTags(const map<std::string, Expression>& tags){
+ auto i = tags.find("interpretation");
+ if (i== tags.end()){
+ return ANY;
+ }
- compilation::Transformations::subscribe<Expression, compilation::TargetInterpretation>(expression);
-}
+ assert(i->second.op == Operator::CALL);
+ const string& cmd = i->second.operands.at(0).getValueString();
-InterpretationResolution
-recognizeTags(const map<std::string, Expression>& tags){
- auto i = tags.find("interpretation");
- if (i== tags.end()){
- return BOTH;
- }
+ //TODO make consistent names of annotation and resolution
+ if (cmd == "force"){
+ return INTR_ONLY;
- assert(i->second.op == Operator::CALL);
- const string& cmd = i->second.operands.at(0).getValueString();
-
- //TODO make consistent names of annotation and resolution
- if (cmd == "force"){
- return INTR_ONLY;
+ } else if (cmd == "suppress"){
+ return CMPL_ONLY;
+ }
- } else if (cmd == "suppress"){
- return CMPL_ONLY;
+ return ANY;
}
-
- return BOTH;
}
+
void
recognizeTags(const Expression& e){
- InterpretationData tag{recognizeTags(e.tags), NONE};
+ InterpretationData tag{details::recognizeTags(e.tags), NONE};
Attachments::put<Expression, InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f){
- return recognizeTags(f->getTags());
+ return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
: AbstractPass(manager) {}
+void InterpretationPass::run(){
+ ManagedFnPtr f = man->root->begin<Function>();
+ auto& visitedSymbols = getSymbolCache();
+
+ while (f.isValid()) {
+ const Symbol& symbolFunction{0, f->getEntryScope()};
+
+ if (!visitedSymbols.isCached(symbolFunction)){
+ visitedSymbols.setCachedValue(symbolFunction, process(f));
+ }
+
+ ++f;
+ }
+}
+
InterpretationResolution
InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl){
recognizeTags(expression);
- InterpretationResolution resolution = BOTH;
+ InterpretationResolution resolution = ANY;
+ InterpretationOperator op = NONE;
switch (expression.__state){
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::IDENT: {
resolution = Parent::processSymbol(expression.getValueString(), context);
break;
}
case Expression::COMPOUND:
break;
default: { resolution = INTR_ONLY; break;}
}
if (expression.__state == Expression::COMPOUND)
switch(expression.op){
case Operator::EQU:
case Operator::NE: {
InterpretationResolution left = process(expression.operands[0], context);
InterpretationResolution right = process(expression.operands[1], context);
resolution = unify(left, right);
break;
}
case Operator::LOGIC_AND: {
assert(expression.operands.size() == 1);
resolution = process (expression.operands[0], context);
break;
}
case Operator::CALL: {
- //TODO cope with static/dynamic context
-
- for (const Expression &op: expression.getOperands()) {
- resolution = unify(resolution, process(op, context));
- }
-
+ //TODO cope with static/dynamic context
+ //TODO BUG here: if several variants they all are processed as CMPL careless of signature
list<ManagedFnPtr> callees = man->root->getFunctionVariants(expression.getValueString());
if (callees.size()!=1){
resolution = CMPL_ONLY;
break;
}
ManagedFnPtr callee = callees.front();
const Symbol& symbCalleeFunc{0, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
const Symbol& symbSelfFunc{0, context.function->getEntryScope()};
- if (symbSelfFunc == symbCalleeFunc){
- break;
+ if (!(symbSelfFunc == symbCalleeFunc)){
+ InterpretationResolution resCallee = processFnCall(callee, context);
+ assert(resCallee != FUNC_POSTPONED && "Indirect recursion detected: can't decide on interpretation resolution");
+
+ resolution = unify(resolution, resCallee);
}
- // - in order to recognize indirect recursion mark this function resolution as POSTPONED
- auto& cache = getSymbolCache();
- if (!cache.isCached(symbSelfFunc)){
- cache.setCachedValue(symbSelfFunc, POSTPONED);
+ //check arguments compatibility
+ const FunctionInterpretationData& sig = FunctionInterpretationHelper::getSignature(callee);
+ for (size_t op=0, size = expression.operands.size(); op < size; ++op){
+ const Expression &operand = expression.operands[op];
+ InterpretationResolution argActual = process(operand, context);
+ if (argActual == ANY) continue;
+
+ assert(sig.signature[op] == argActual);
}
- InterpretationResolution resCallee = process(callee);
- if (resCallee == POSTPONED){
- assert(false && "Indirect recursion detected: can't decide on interpretation resolution");
+ if (FunctionInterpretationHelper::needPartialInterpretation(callee)){
+ op= CALL_INTERPRET_PARTIAL;
}
- resolution = unify(resolution, resCallee);
break;
}
case Operator::IF:{
InterpretationResolution flagCondition = process(expression.getOperands()[0], context);
InterpretationResolution flagScope1 = Parent::process(expression.blocks.front(), context);
InterpretationResolution flagScope2 = Parent::process(expression.blocks.back(), context);
//special case: IF_INTERPRET_CONDITION
if (checkConstraints<QUERY_INTR_ONLY>({flagCondition})){
- setSpecializedOperator(expression, IF_INTERPRET_CONDITION);
- flagCondition = BOTH;
+ op= IF_INTERPRET_CONDITION;
+ flagCondition = ANY;
}
resolution = unify(flagCondition, flagScope1, flagScope2);
break;
}
case Operator::FOLD: {
InterpretationResolution flagInput = process(expression.getOperands()[0], context);
InterpretationResolution flagAccumInit = process(expression.getOperands()[1], context);
CodeScope* scopeBody = expression.blocks.front();
const std::string& nameEl = expression.bindings[0];
getSymbolCache().setCachedValue(scopeBody->findSymbol(nameEl), InterpretationResolution(flagInput));
const std::string& nameAccum = expression.bindings[1];
getSymbolCache().setCachedValue(scopeBody->findSymbol(nameAccum), InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody = Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if (checkConstraints<QUERY_INTR_ONLY>({flagInput})){
- setSpecializedOperator(expression, FOLD_INTERPRET_INPUT);
- flagInput = BOTH;
+ op= FOLD_INTERPRET_INPUT;
+ flagInput = ANY;
}
resolution = unify(flagInput, flagAccumInit, flagBody);
break;
}
case Operator::INDEX: {
resolution = unify(
process(expression.operands[0], context),
Parent::processSymbol(expression.getValueString(), context)
);
break;
}
case Operator::SWITCH: {
InterpretationResolution flagCondition = process(expression.operands[0], context);
bool hasDefaultCase = expression.operands[1].op == Operator::CASE_DEFAULT;
//determine conditions resolution
InterpretationResolution flagHeaders = flagCondition;
for (size_t size = expression.operands.size(), i= hasDefaultCase? 2: 1; i<size; ++i){
const Expression& exprCase = expression.operands[i];
flagHeaders = unify(flagHeaders, Parent::process(exprCase.blocks.front(), context));
}
if (checkConstraints<QUERY_INTR_ONLY>({flagHeaders})){
- setSpecializedOperator(expression, SWITCH_INTERPRET_CONDITION);
- flagHeaders = BOTH;
+ op= SWITCH_INTERPRET_CONDITION;
+ flagHeaders = ANY;
}
//determine body resolutions
resolution = flagHeaders;
for (size_t size = expression.operands.size(), i= 1; i<size; ++i){
const Expression& exprCase = expression.operands[i];
resolution = unify(resolution, Parent::process(exprCase.blocks.back(), context));
}
break;
}
case Operator::LIST:
case Operator::LIST_NAMED: {
for (const Expression &op: expression.getOperands()) {
resolution = unify(resolution, process(op, context));
}
break;
}
default: {
resolution = CMPL_ONLY;
Parent::process(expression, context, decl);
break;
}
}
- InterpretationResolution resolutionExpected = Attachments::get<Expression, InterpretationData>(expression, {BOTH, NONE})
+ InterpretationResolution resolutionExpected = Attachments::get<Expression, InterpretationData>(expression, {ANY, NONE})
.resolution;
resolution = unify(resolution, resolutionExpected);
+ if (op!=NONE || resolution == INTR_ONLY ){
+ Attachments::put<Expression, InterpretationData>(expression, {resolution, op});
+ }
+
if (resolution == INTR_ONLY){
- Attachments::put<Expression, InterpretationData>(expression, {INTR_ONLY, NONE});
compilation::Transformations::subscribe<Expression, compilation::TargetInterpretation>(expression);
}
-
return resolution;
}
InterpretationResolution
- InterpretationPass::process(ManagedFnPtr function){
- InterpretationResolution resExpected = recognizeTags(function);
+ InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context){
+ const Symbol& symbolFunction{0, function->getEntryScope()};
+ auto& visitedSymbols = getSymbolCache();
- //mark preliminary function resolution same as expected
- if (resExpected != BOTH){
- const Symbol& symbSelfFunc{0, function->getEntryScope()};
- getSymbolCache().setCachedValue(symbSelfFunc, move(resExpected));
- }
+ if (visitedSymbols.isCached(symbolFunction))
+ return visitedSymbols.getCachedValue(symbolFunction);
+
+ PassContext context2;
+ context2.function = function;
+ return visitedSymbols.setCachedValue(symbolFunction,
+ Parent::process(function->getEntryScope(), context2));
+ }
+
+ InterpretationResolution
+ InterpretationPass::process(ManagedFnPtr function){
CodeScope* entry = function->getEntryScope();
+ std::vector<std::string> arguments = entry->__bindings;
+ const Symbol& symbSelfFunc{0, function->getEntryScope()};
auto& cache = getSymbolCache();
- std::vector<std::string> args = entry->__bindings;
- for (int argNo = 0, size = args.size(); argNo< size; ++argNo){
- Symbol symbArg = entry->findSymbol(args[argNo]);
- InterpretationResolution resArg = recognizeTags(entry->findDeclaration(symbArg).tags);
- cache.setCachedValue(symbArg, move(resArg));
+ const FunctionInterpretationData& dataIntrpr = FunctionInterpretationHelper::getSignature(function);
+ InterpretationResolution resExpected = details::recognizeTags(function->getTags());
+
+ //mark preliminary function resolution as expected
+ if (resExpected != ANY){
+ cache.setCachedValue(symbSelfFunc, move(resExpected));
+
+ } else {
+ // - in order to recognize indirect recursion mark this function resolution as POSTPONED
+ cache.setCachedValue(symbSelfFunc, FUNC_POSTPONED);
+ }
+
+ //set resolution for function arguments as expected
+ for (int argNo = 0, size = arguments.size(); argNo< size; ++argNo){
+ Symbol symbArg = entry->findSymbol(arguments[argNo]);
+ cache.setCachedValue(symbArg, InterpretationResolution(dataIntrpr.signature[argNo]));
}
InterpretationResolution resActual = Parent::process(function);
return unify(resActual, resExpected);
}
+
+ const FunctionInterpretationData
+ FunctionInterpretationHelper::getSignature(ManagedFnPtr function){
+ const Symbol& symbFunc{0, function->getEntryScope()};
+
+ if (Attachments::exists<Symbol, FunctionInterpretationData>(symbFunc)){
+ return Attachments::get<Symbol, FunctionInterpretationData>(symbFunc);
+ }
+
+ FunctionInterpretationData&& data = recognizeSignature(function);
+ Attachments::put<Symbol, FunctionInterpretationData>(symbFunc, data);
+ return data;
+ }
+
+ FunctionInterpretationData
+ FunctionInterpretationHelper::recognizeSignature(ManagedFnPtr function){
+ CodeScope* entry = function->__entry;
+ FunctionInterpretationData result;
+ result.signature.reserve(entry->__bindings.size());
+
+ bool flagPartialInterpretation = false;
+ for(size_t no=0, size=entry->__bindings.size(); no < size; ++no){
+ const std::string& argName = entry->__bindings[no];
+ const Expression& arg = entry->findDeclaration(entry->findSymbol(argName));
+
+ InterpretationResolution argResolution = details::recognizeTags(arg.tags);
+ flagPartialInterpretation |= (argResolution == INTR_ONLY);
+
+ result.signature.push_back(argResolution);
+ }
+ result.flagPartialInterpretation = flagPartialInterpretation;
+ return result;
+ }
+
+ bool FunctionInterpretationHelper::needPartialInterpretation(ManagedFnPtr function){
+ const FunctionInterpretationData& data = getSignature(function);
+ return data.flagPartialInterpretation;
+ }
}
--
\ No newline at end of file
+
+//if (res != INTR_ONLY){
+// argumentsActual.insert(no);
+//}
+
+
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
index 0992d6e..0d6ba84 100644
--- a/cpp/src/pass/interpretationpass.h
+++ b/cpp/src/pass/interpretationpass.h
@@ -1,47 +1,78 @@
/*
* File: interpretationpass.h
* Author: pgess
*
* Created on July 5, 2016, 5:21 PM
*/
#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H
#include "abstractpass.h"
+#include <map>
namespace xreate {
- enum InterpretationResolution{BOTH, INTR_ONLY, CMPL_ONLY, POSTPONED};
- enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION};
+ enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
+ enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION, CALL_INTERPRET_PARTIAL};
struct InterpretationData{
InterpretationResolution resolution;
InterpretationOperator op;
};
template<>
InterpretationResolution
defaultValue<InterpretationResolution>();
+ struct FunctionInterpretationData{
+ typedef std::vector<InterpretationResolution> Signature;
+ Signature signature;
+ bool flagPartialInterpretation;
+ };
+
+ template<>
+ struct AttachmentsDict<FunctionInterpretationData>
+ {
+ typedef FunctionInterpretationData Data;
+ static const unsigned int key = 5;
+ };
+
+ class FunctionInterpretationHelper {
+ public:
+ static const FunctionInterpretationData
+ getSignature(ManagedFnPtr function);
+
+ static bool needPartialInterpretation(ManagedFnPtr function);
+
+ private:
+ static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
+ };
+
template<>
struct AttachmentsDict<InterpretationData>
{
typedef InterpretationData Data;
static const unsigned int key = 3;
};
class InterpretationPass: public AbstractPass<InterpretationResolution> {
typedef AbstractPass<InterpretationResolution> Parent;
public:
InterpretationResolution process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
InterpretationResolution process(ManagedFnPtr function);
+ InterpretationResolution processFnCall(ManagedFnPtr function, PassContext context);
InterpretationPass(PassManager* manager);
+ void run();
};
+
+ namespace details {
+ InterpretationResolution recognizeTags(const std::map<std::string, Expression>& tags);
+ }
}
#endif /* INTERPRETATIONPASS_H */
diff --git a/cpp/src/query/context.cpp b/cpp/src/query/context.cpp
index efa6af1..76d7b05 100644
--- a/cpp/src/query/context.cpp
+++ b/cpp/src/query/context.cpp
@@ -1,244 +1,207 @@
/*
* 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 {
const Domain domainEmpty;
const Decisions decisionsEmpty;
const FunctionDemand functionDemandEmpty;
-bool operator < (const Expression&a, const Expression&b) {
- if (a.__state != b.__state) return a.__state < b.__state;
- assert(a.__state != Expression::INVALID);
- switch(a.__state) {
- case Expression::IDENT:
- case Expression::STRING:
- case Expression::VARIANT:
- return a.getValueString() < b.getValueString();
-
- case Expression::NUMBER:
- return a.getValueDouble() < b.getValueDouble();
-
- case Expression::COMPOUND: {
- assert(a.op == Operator::CALL);
- assert(a.blocks.size()==0);
- assert(b.blocks.size()==0);
-
- if (a.operands.size() != b.operands.size()){
- return (a.operands.size() < b.operands.size());
- }
-
- if (a.getValueString() != b.getValueString()){
- return a.getValueString() < b.getValueString();
- }
-
- for(size_t i=0; i<a.operands.size(); ++i){
- bool result = a.operands[i] < b.operands[i];
- if (result) return true;
- }
-
- return false;
- }
-
- case Expression::BINDING:
- case Expression::INVALID:
- assert(false);
- }
-
- return false;
-}
-
ContextQuery::ContextQuery(){}
const Domain&
ContextQuery::getContext(const ScopePacked& scopeId) const{
if (!__modelContext.count(scopeId)){
return domainEmpty;
}
return __modelContext.at(scopeId);
}
const Domain&
ContextQuery::getContext(CodeScope* const scope) const{
return getContext(clasp->pack(scope));
}
+
//DEBT compatibility of forced context with context resolution for interpretation
void
ContextQuery::forceContext(const ScopePacked& scopeId, std::list<Expression> context){
// TODO remove forced context of the same class/type only, possibly
- //remove any previous forced context for this scopeId
+ //remove any previous forced context for this 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");
+ const std::string& atomBinding = Config::get("clasp.bindings.scope");
this->clasp = clasp;
- ClaspLayer::ModelFragment query = clasp->query(atomEarlyBinding);
+ ClaspLayer::ModelFragment query = clasp->query(atomBinding);
//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);
- dictContext[idScope].push_back(context);
+ std::string link;
+ tie(idScope, context, link) = ClaspLayer::parse<ScopePacked, Expression, string>(i->second);
+ if (link == "strong") {
+ dictContext[idScope].push_back(context);
+ }
}
for (map<ScopePacked, vector<Expression>>::value_type& entry: dictContext){
__modelContext.insert(move(entry));
}
}
prepareFunctionDemandModel();
prepareDecisionModels();
}
void
ContextQuery::prepareFunctionDemandModel(){
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;
Expression topic;
tie(function, topic) = ClaspLayer::parse<string, Expression>(i->second);
FunctionDemand& demand = __modelFunctionDemand[function];
demand.left.insert(make_pair(demand.left.size(), topic));
}
}
void
ContextQuery::prepareDecisionModels(){
const std::string& atomDecision = Config::get("clasp.bindings.scope_decision");
const std::string& atomDependentDecision = Config::get("clasp.context.decisions.dependent");
std::multimap<Expression, Expression> modelDomains;
ClaspLayer::ModelFragment query = clasp->query(atomDecision);
if (query){
for (auto i = query->first; i!=query->second; ++i){
ScopePacked scopeId;
Expression topic;
Expression decision;
std::tie(scopeId, topic, decision) = ClaspLayer::parse<ScopePacked, Expression, Expression>(i->second);
if (decision.getValueString() == atomDependentDecision) {
assert(decision.operands.size() == 2);
const Expression& decisionGuard = decision.operands[1];
const Expression& decisionValue = decision.operands[0];
__modelDependentDecisions[scopeId][topic].emplace(decisionGuard, decisionValue);
modelDomains.emplace(topic, decisionValue);
} else {
Decisions& decisionsOfScope = __modelStaticDecisions[scopeId];
assert(decisionsOfScope.emplace(topic, decision).second && "Possibly more than one decision");
modelDomains.emplace(topic, decision);
}
}
}
//populate topic domains:
auto adapter = [](const std::pair<const Expression&,const Expression>& p){ return p.second; };
auto iBegin = modelDomains.begin();
while (iBegin!=modelDomains.end()){
const Expression topic = iBegin->first;
auto iEnd = modelDomains.upper_bound(topic);
auto iBeginAdapted = boost::make_transform_iterator(iBegin,adapter);
auto iEndAdapted = boost::make_transform_iterator(iEnd,adapter);
Domain dom(iBeginAdapted, iEndAdapted);
__modelTopicDomains.emplace(topic, move(dom));
iBegin = iEnd;
}
}
const FunctionDemand&
ContextQuery::getFunctionDemand(const std::string& name) const {
if (__modelFunctionDemand.count(name)){
return __modelFunctionDemand.at(name);
}
return functionDemandEmpty;
}
const Decisions&
ContextQuery::getFinalDecisions(const ScopePacked& scopeId) const{
if (__modelStaticDecisions.count(scopeId)){
return __modelStaticDecisions.at(scopeId);
}
return decisionsEmpty;
}
const Domain&
ContextQuery::getTopicDomain(const Expression& topic) const{
if (__modelTopicDomains.count(topic)){
return __modelTopicDomains.at(topic);
}
return domainEmpty;
}
const DependentDecision&
ContextQuery::getDependentDecision(ScopePacked scope, const Expression& topic) const{
auto itDecisionsAllTopics = __modelDependentDecisions.find(scope);
if (itDecisionsAllTopics != __modelDependentDecisions.end()){
auto itDecisions = itDecisionsAllTopics->second.find(topic);
if (itDecisions != itDecisionsAllTopics->second.end()){
return itDecisions->second;
}
}
return decisionsEmpty;
}
// 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 b32a021..8dd6858 100644
--- a/cpp/src/query/context.h
+++ b/cpp/src/query/context.h
@@ -1,97 +1,95 @@
/*
* 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 "serialization.h"
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
namespace xreate {
typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
typedef boost::bimap<size_t, Expression> FunctionDemand;
typedef std::map<Expression, Expression> Decisions;
typedef std::map<Expression, Expression> DependentDecision;
class ContextQuery: public IQuery {
//AdhocQuery();
public:
const Domain& getContext(const ScopePacked& scopeId) const;
const Domain& getContext(CodeScope* const scope) const;
void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
const Domain& getTopicDomain(const Expression& topic) const;
const DependentDecision& getDependentDecision(ScopePacked scope, const Expression& topic) const;
const FunctionDemand& getFunctionDemand(const std::string& name) const;
const Decisions& getFinalDecisions(const ScopePacked& scopeId) const;
virtual void init(ClaspLayer* clasp);
ContextQuery();
virtual ~ContextQuery(){};
private:
ClaspLayer* clasp;
std::map<ScopePacked, Domain> __modelContext;
std::map<std::string, FunctionDemand> __modelFunctionDemand;
std::map<ScopePacked, Decisions> __modelStaticDecisions;
std::map<Expression, Domain> __modelTopicDomains;
std::map<ScopePacked, std::map<Expression, DependentDecision>> __modelDependentDecisions;
void prepareFunctionDemandModel();
void prepareDecisionModels();
};
-bool operator < (const Expression&, const Expression&);
-
} /* 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 ;
*/
#endif /* SRC_QUERY_CONTEXT_H_ */
diff --git a/cpp/tests/adhoc-skipdetection.cpp b/cpp/tests/adhoc-skipdetection.cpp
index 603891c..6dcb4f5 100644
--- a/cpp/tests/adhoc-skipdetection.cpp
+++ b/cpp/tests/adhoc-skipdetection.cpp
@@ -1,34 +1,34 @@
/*
* skipdetection.cpp
*
* Created on: Jul 10, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "clasplayer.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
//TASK implement loop "skip" command
-TEST(Adhoc_Loop_SkipDetection, testNoneValueTagExists){
+TEST(Adhoc_Loop_SkipDetection, DISABLED_testNoneValueTagExists){
PassManager* man = PassManager::prepareForCode
- ("test = function():: int; entry {\n"
+ ("test = function:: int; entry {\n"
" data = [1..5]::[int].\n"
" \n"
- " result = loop fold(data->i::int, 0->sum::int)::int{\n"
- " if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
+ " result = loop fold(data->i::int, 0->sum)::int{\n"
+ " if (i==3)::bool {valNull = null. valNull} else {i+sum}\n"
" }.\n"
" \n"
" result\n"
"}");
man->runWithoutCompilation();
ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.nonevalue"));
int countNoneValue = 0;
if (answer)
countNoneValue = std::distance(answer->first, answer->second);
EXPECT_EQ(1, countNoneValue);
}
diff --git a/cpp/tests/adhoc.cpp b/cpp/tests/adhoc.cpp
index 5719e57..eb9bafb 100644
--- a/cpp/tests/adhoc.cpp
+++ b/cpp/tests/adhoc.cpp
@@ -1,157 +1,160 @@
/*
* adhoc-exceptions.cpp
*
* Created on: Nov 19, 2015
* Author: pgess
*/
class Adhoc_pass_Adhoc1_Test;
#define FRIEND_ADHOC_UNITTESTS \
friend class ::Adhoc_pass_Adhoc1_Test;
#include "ast.h"
#include "passmanager.h"
#include "gtest/gtest.h"
#include <stdio.h>
#include <memory>
#include <sstream>
#include <stdlib.h>
#include "pass/adhocpass.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
using namespace xreate;
using namespace std;
TEST(Adhoc, ast_operatorAdhoc1){
PassManager* man = PassManager::prepareForCode (
" test = "
"function:: int {\n"
" ad hoc Exception(NonImplemented)\n"
" }"
);
- Expression subject = man->root->findFunction("test")->getEntryScope()->__body;
+ Expression subject = man->root->findFunction("test")->getEntryScope()->getBody();
ASSERT_EQ(Operator::ADHOC, subject.op);
ASSERT_EQ(1, subject.getOperands().size());
Expression exception = subject.getOperands()[0];
ASSERT_EQ("Exception", exception.getValueString());
}
TEST(Adhoc, ast_schemeAdhoc1){
PassManager* man = PassManager::prepareForCode (
"interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case Error {false}\n"
" case Success {true}\n"
" }\n"
" }");
assert(man->root->__interfacesData.count(ASTInterface::Adhoc));
Expression adhocData = man->root->__interfacesData.find(ASTInterface::Adhoc)->second;
ASSERT_EQ(Operator::SWITCH, adhocData.operands[0].op);
}
TEST(Adhoc, pass_Adhoc1){
PassManager* man = PassManager::prepareForCode (
"interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case Error {false}\n"
" case Success {true}\n"
" }\n"
- " }");
+ "}\n"
+
+ "main = function::int; entry {0} \n"
+ );
man->runWithoutCompilation();
AdhocPass* pass = reinterpret_cast<AdhocPass* >(man->getPassById(PassId::AdhocPass));
EXPECT_TRUE(pass->__schemes.size() > 0);
AdhocScheme* scheme = pass->__schemes.begin()->second;
EXPECT_EQ("expectNoErrors", scheme->getContext());
}
TEST(Adhoc, full_1){
PassManager* man = PassManager::prepareForCode (
" import raw (\"core/control-context.lp\")"
" interface(adhoc){\n"
" pre function expectNoErrors:: bool {\n"
" case Error {0}\n"
" case Success {1}\n"
" }\n"
" }"
" test1 = pre function {\n"
" context:: expectNoErrors."
" ad hoc \"Success\"\n"
" }"
"main = function::bool;entry {\n"
" test1()\n"
" }");
bool (*main)() = (bool (*)()) man->run();
bool result = main();
ASSERT_EQ(true, result);
}
TEST(Adhoc, full_contextExpectNoErrrors){
PassManager* man = PassManager::prepareForCode (
- " import raw (\"core/control-context.lp\")\n"
+ "import raw (\"core/control-context.lp\")\n"
"interface(extern-c){\n"
" xml2 = library:: pkgconfig(\"libxml-2.0\").\n"
" \n"
" include {\n"
" xml2 = [\"stdlib.h\"]\n"
" }.\n"
"}"
- " interface(adhoc){\n"
- " pre function expectNoErrors:: bool {\n"
- " case Error {0}\n"
- " case Success {1}\n"
- " }\n"
+ "interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case Error {0}\n"
+ " case Success {1}\n"
" }\n"
+ "}\n"
- " expectErrorCode = pre function(x::int){\n"
- " if (x==0)::bool {ad hoc \"Success\"}\n"
- " else {ad hoc \"Error\"}\n"
- " }\n"
+ "expectErrorCode = pre function(x::int){\n"
+ " if (x==0)::bool {ad hoc \"Success\"}\n"
+ " else {ad hoc \"Error\"}\n"
+ "}\n"
- " main = function::bool; entry {\n"
- " context:: expectNoErrors."
- " expectErrorCode(system(\"ls -la\"))\n"
- " }" );
+ "main = function::bool; entry {\n"
+ " context:: expectNoErrors."
+ " expectErrorCode(system(\"ls -la\"))\n"
+ "}" );
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(1, main());
}
TEST(Adhoc, ast_switchAdhoc1){
PassManager* man = PassManager::prepareForCode (
"test1 = function:: bool {\n"
" switch ad hoc (x:: errors)\n"
" case ERROR {0}\n"
" case SUCCESS {1}\n"
" \n"
" }"
);
- Expression eSwitch = man->root->findFunction("test1")->getEntryScope()->__body;
+ Expression eSwitch = man->root->findFunction("test1")->getEntryScope()->getBody();
EXPECT_EQ(Operator::SWITCH_ADHOC, eSwitch.op);
EXPECT_EQ(3, eSwitch.operands.size());
EXPECT_EQ(1, eSwitch.tags.size());
EXPECT_EQ("errors", eSwitch.tags.begin()->first);
Expression eCondition = eSwitch.getOperands()[0];
EXPECT_EQ("x", eCondition.getValueString());
}
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index 4868d3a..46c637d 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,49 +1,48 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Parser.h"
using namespace std;
using namespace xreate;
TEST(AST, Containers1){
FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
+ assert(!parser.errors->count && "Parser errors");
- const AST& ast = parser.root;
-
- fclose(input);
+ fclose(input);
}
TEST(AST, InterfacesDataCFA) {
PassManager* man = PassManager::prepareForCode
("interface(cfa){\n"
" operator map :: annotation1.\n"
"}");
auto answer = man->root->__interfacesData.equal_range(CFA);
EXPECT_EQ(1, std::distance(answer.first, answer.second));
Expression&& scheme = move(answer.first->second);
EXPECT_EQ(Operator::MAP, scheme.op);
EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString());
}
TEST(AST, DISABLED_InterfacesDataDFA){
}
TEST(AST, DISABLED_InterfacesDataExtern){
}
//TODO xreate.atg: replace all Type<> as ExprAnnotations<>
diff --git a/cpp/tests/basic.cpp b/cpp/tests/basic.cpp
index 1f1acb5..0deb63b 100644
--- a/cpp/tests/basic.cpp
+++ b/cpp/tests/basic.cpp
@@ -1,26 +1,26 @@
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
using namespace xreate;
TEST(Basic, functionEntry1){
std::unique_ptr<PassManager> program(PassManager::prepareForCode(
"func1 = function(a:: int):: int {a+8} \
- func2 = function()::int; entry {12 + func1(4)} \
+ func2 = function::int; entry {12 + func1(4)} \
"));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = entry();
ASSERT_EQ(24, answer);
}
diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp
index e9b7e0c..f01028c 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,109 +1,119 @@
/*
* testsCFG.cpp
*
* Created on: Jul 17, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "pass/dfapass.h"
#include "pass/cfapass.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include "gtest/gtest.h"
#include <boost/scoped_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
using namespace xreate;
using namespace std;
-TEST(CFG, testFunctionAnnotationsClasp){
- string&& program =
- "f2 = function::int; annotationF2 {\n"
- " 0\n"
- "}\n"
- "\n"
- "f1 = function:: int; entry; annotationF1 {\n"
- " f2() + 10\n"
- "}";
-
-
- PassManager* man = PassManager::prepareForCode(move(program));
- man->runWithoutCompilation();
-
- ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1");
- int countNoneValue = 0;
- if (answer)
- countNoneValue = std::distance(answer->first, answer->second);
- EXPECT_EQ(1, countNoneValue);
-
- answer = man->clasp->query("annotationF2");
- countNoneValue = 0;
- if (answer)
- countNoneValue = std::distance(answer->first, answer->second);
+TEST(CFA, testFunctionAnnotationsClasp){
+ string&& program =
+ "f2 = function::int; annotationF2 {\n"
+ " 0\n"
+ "}\n"
+ "\n"
+ "f1 = function:: int; entry; annotationF1 {\n"
+ " f2() + 10\n"
+ "}";
+
+
+ PassManager* man = PassManager::prepareForCode(move(program));
+ man->runWithoutCompilation();
+
+ ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1");
+ int countNoneValue = 0;
+ if (answer) countNoneValue = std::distance(answer->first, answer->second);
+ EXPECT_EQ(1, countNoneValue);
+
+ answer = man->clasp->query("annotationF2");
+ countNoneValue = 0;
+ if (answer) countNoneValue = std::distance(answer->first, answer->second);
+
EXPECT_EQ(1, countNoneValue);
}
-TEST(CFG, testLoopContextExists){
- PassManager* man = PassManager::prepareForCode (
- "interface(cfa){\n"
- " operator fold:: annotation1.\n"
- "}\n"
- "\n"
- "main = function:: int; entry {\n"
- " x = [1..10]:: [int].\n"
- " sum = loop fold (x->el:: int, 0->sum):: int {\n"
- " el + sum + f1()\n"
- " }. \n"
- " sum\n"
- "}"
- "f1 = function::int {\n"
- " x = 0:: int. "
- " x\n"
- "}"
+TEST(CFA, testLoopContextExists){
+ PassManager* man = PassManager::prepareForCode (
+ "interface(cfa){\n"
+ " operator fold:: annotation1.\n"
+ "}\n"
+ "\n"
+ "main = function:: int; entry {\n"
+ " x = [1..10]:: [int].\n"
+ " sum = loop fold (x->el:: int, 0->sum):: int {\n"
+ " el + sum + f1()\n"
+ " }. \n"
+ " sum\n"
+ "}"
+ "case context:: annotation1 {"
+ " f1 = function::int {\n"
+ " x = 0:: int. "
+ " x\n"
+ " }"
+ "}"
);
- man->runWithoutCompilation();
+ man->runWithoutCompilation();
+ ClaspLayer::ModelFragment model = man->clasp->query("annotation1");
+ ScopePacked scopeIdActual = std::get<0>(ClaspLayer::parse<ScopePacked>(model->first->second));
+
+ CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
+ Symbol symbSum = man->root->findFunction("main")->getEntryScope()->findSymbol("sum");
+ CodeScope* scopeExpected = scopeEntry->findDeclaration(symbSum).blocks.front();
+
+ ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected);
+ ASSERT_EQ(scopeIdExpected, scopeIdActual);
}
-TEST(CFG, CFGRoots){
- std::string program =
+TEST(CFA, CFGRoots){
+ std::string program =
R"CODE(
main = function::int{a()+ b()}
a= function::int {c1() + c2()}
b= function::int {c2()}
c1=function::int{0}
c2=function::int{0}
)CODE";
-
+
boost::scoped_ptr<PassManager> manager
(PassManager::prepareForCode(move(program)));
-
+
manager->registerPass(new CFAPass(manager.get()) , PassId::CFGPass);
manager->executePasses();
manager->clasp->run();
-
+
DominatorsTreeAnalysisProvider domProvider;
domProvider.run(manager->clasp);
-
+
DominatorsTreeAnalysisProvider::Dominators expectedFDom= {
{0, {0, 9}}
,{1, {1, 4}}
,{2, {7, 8}}
,{3, {2, 3}}
,{4, {5, 6}}
};
-
+
DominatorsTreeAnalysisProvider::Dominators expectedPostDom= {
{0, {5, 6}}
,{1, {3, 4}}
,{2, {8, 9}}
,{3, {1, 2}}
,{4, {7, 10}}
};
-
+
ASSERT_EQ(expectedFDom, domProvider.getForwardDominators());
ASSERT_EQ(expectedPostDom, domProvider.getPostDominators());
}
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index 58cb59d..e5371df 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,62 +1,80 @@
#include "passmanager.h"
#include "gtest/gtest.h"
using namespace xreate;
+//DEBT implement no pkgconfig ways to link libs
//TOTEST 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());
+ 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, Sequence2){
+ 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"
+ " context:: expectNoErrors. "
+ " buf1 = \"aaaaa\"::string.\n"
+ " buf2 = \"aaaaa\"::string.\n"
+ " sequence ["
+ " sprintf(buf1, \"%d\", system(\"bazaar --version\")),"
+ " sprintf(buf2, \"%d\", system(\"svn --version\")),"
+ " printf(buf1),\n"
+ " printf(buf2)\n"
+ "]"
+ "}"
+ );
+
+ int (*main)() = (int (*)()) man->run();
+ main();
+}
+
+
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));
+ 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 e2c3e76..2f21eee 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 "passmanager.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);
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);
+ ASSERT_EQ(17, answer);
fclose(input);
}
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
index 4c05c02..9a3187c 100644
--- a/cpp/tests/context.cpp
+++ b/cpp/tests/context.cpp
@@ -1,370 +1,404 @@
/*
* frame-context.cpp
*
* Created on: Dec 3, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "query/context.h"
#include "gtest/gtest.h"
#include <iostream>
#include <boost/scoped_ptr.hpp>
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 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));
-//}
+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"
+
+ "test = function(cmnd:: int):: int; entry {\n"
+ " if (cmnd > 0)::int {testA()} else {testB()} \n"
+ "}\n"
+ );
+
+ ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
+ man->runWithoutCompilation();
+
+ CodeScope* scopeTestC = man->root->findFunction("testC")->getEntryScope();
+ const Domain& context = query->getContext(man->clasp->pack(scopeTestC));
+
+ int contextSize = context.size();
+ EXPECT_EQ(2, contextSize);
+}
+
+TEST(Context, full_ContextBasedFunctionSpecialization){
+
+ PassManager* man = PassManager::prepareForCode(
+ " import raw (\"core/control-context.lp\")\n"
+ " 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));
+}
+
+//TOODO recover context loop and enable the test
+TEST(Context, DISABLED_full_LoopContext){
+
+ PassManager* man = PassManager::prepareForCode(
+ " import raw (\"core/control-context.lp\")\n"
+ " 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(
+ " import raw (\"core/control-context.lp\")\n"
+ " 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->getBody();
+ CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front();
+ ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
+ const Domain& 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 FunctionDemand& demMain = queryContext->getFunctionDemand("main");
+ ASSERT_EQ(0, demMain.size());
+
+ const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate");
+ ASSERT_EQ(1, demCalculate.size());
+
+ int (*entry)(int) = (int (*)(int)) man->run();
+ ASSERT_EQ(1000, entry(0));
+ ASSERT_EQ(100, entry(1));
+}
+
+TEST(Context, testLoopContextExists){
+ PassManager* man = PassManager::prepareForCode (
+ "import raw (\"core/control-context.lp\")\n"
+
+ "interface(cfa){\n"
+ " operator fold:: annotation1.\n"
+ "}\n"
+ "\n"
+ "main = function:: int; entry {\n"
+ " x = [1..10]:: [int].\n"
+ " sum = loop fold (x->el:: int, 0->sum):: int {\n"
+ " el + sum + f1()\n"
+ " }. \n"
+ " sum\n"
+ "}"
+ "case context:: annotation1 {"
+ " f1 = function::int {\n"
+ " x = 0:: int. "
+ " x\n"
+ " }"
+ "}"
+ );
+
+ man->run();
+}
TEST(Context, pathDependent_context){
- std::string program =
+ std::string program =
R"CODE(
import raw("core/control-context.lp")
convert = function(length:: num) :: num {
0
}
-
+
case context:: convert(milli, meters) {
convert = function(length:: num) :: num {
1000 * length
}
}
case context:: convert(centi, meters) {
convert = function(length:: num) :: num {
100 * length
}
}
case context:: convert(centi, kilo) {
convert = function(length:: num) :: num {
100000 * length
}
}
case context:: convert(milli, kilo) {
convert = function(length:: num) :: num {
1000000 * length
}
}
-
+
main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{
switch (unitsInput)::num
case 0 {
test_fromMilli(value, unitsOutput)
}
case 1 {
test_fromCenti(value, unitsOutput)
}
- case default {0}
+ case default {0}
}
test_fromCenti = function(value::num, output::num)::num{
context:: input(centi).
-
+
switch(output):: num
case 0 {
toMeters(value)
}
-
+
case 1 {
toKilo(value)
}
-
+
case default {0}
}
-
+
test_fromMilli = function(value::num, output::num)::num{
context:: input(milli).
-
+
switch(output):: num
case 0 {
toMeters(value)
}
-
+
case 1 {
toKilo(value)
}
-
+
case default {0}
}
toMeters = function(value::num)::num {
rule context:: convert(X, meters) case input(X) {true}
-
+
doConvert(value)
}
toKilo = function(value::num)::num {
rule context:: convert(X, kilo) case input(X) {true}
-
+
doConvert(value)
}
doConvert = function(value::num)::num{
- convert(value)
+ convert(value)
})CODE";
-
+
boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
man->runWithoutCompilation();
-
+
int (*test)(int, int, int) = (int (*)(int, int, int))man->run();
-
+
enum {INPUT_MILLI, INPUT_CENTI};
enum {OUTPUT_METERS, OUTPUT_KILO};
-
+
ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO));
ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS));
-}
+}
diff --git a/cpp/tests/dfa.cpp b/cpp/tests/dfa.cpp
index 088bc40..f9a4fb8 100644
--- a/cpp/tests/dfa.cpp
+++ b/cpp/tests/dfa.cpp
@@ -1,42 +1,12 @@
/*
* DFGtests.cpp
*
* Created on: Jul 23, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "pass/dfapass.h"
#include "gtest/gtest.h"
using namespace xreate;
-using namespace std;
-
-TEST(DFG, testFunctionRetSymbolExists){
- PassManager* man = PassManager::prepareForCode
- ("test = function():: int; entry {\n"
- " data = [1..5]::[int].\n"
- " \n"
- " result = loop fold(data->i::int, 0->sum::int)::int{\n"
- " if (i==3)::int {valNull = null. valNull} else {i+sum}\n"
- " }.\n"
- " \n"
- " result\n"
- "}");
-
- man->runWithoutCompilation();
- ClaspLayer::ModelFragment answer = man->clasp->query(Config::get("clasp.ret.symbol"));
-
- if (answer)
- EXPECT_EQ(1, std::distance(answer->first, answer->second));
-
- for (auto functionIt = answer->first; functionIt != answer->second; ++functionIt){
- auto ret = ClaspLayer::parse<string, Gringo::Symbol>(functionIt->second);
-
- ASSERT_EQ("test", std::get<0>(ret));
-
- SymbolPacked symbolRet = std::get<0>(ClaspLayer::parse<SymbolPacked>(std::get<1>(ret)));
- ASSERT_EQ(3, symbolRet.identifier);
- ASSERT_EQ(0, symbolRet.scope);
- }
-}
-
+using namespace std;
\ No newline at end of file
diff --git a/cpp/tests/diagnostic-messages.cpp b/cpp/tests/diagnostic-messages.cpp
index dbd21a1..66d2db1 100644
--- a/cpp/tests/diagnostic-messages.cpp
+++ b/cpp/tests/diagnostic-messages.cpp
@@ -1,32 +1,32 @@
/*
* diagnostic-messages.cpp
*
* Created on: Oct 27, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "pass/dfapass.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate;
-TEST(Diagnostic_DFA, DISABLED_recursion1){
+TEST(Diagnostic, DISABLED_DFA_recursion1){
- //Error while processing recursion, There should be some diagnostic complaints
- std::string code = \
- "test1 = function()::[int] {\n"
- " varRecursion = loop map(varRecursion->el:: int)::[int]{\n"
- " el\n"
- " }.\n"
- " \n"
- " varRecursion\n"
- "}";
+ //TODO Error while processing recursion, There should be some diagnostic complaints here
+ std::string code = \
+ "test1 = function::[int] {\n"
+ " varRecursion = loop map(varRecursion->el:: int)::[int]{\n"
+ " el\n"
+ " }.\n"
+ " \n"
+ " varRecursion\n"
+ "}";
- PassManager* man = PassManager::prepareForCode(move(code));
- DFAPass* pass = new DFAPass(man);
- pass->run();
- pass->finish();
+ PassManager* man = PassManager::prepareForCode(move(code));
+ DFAPass* pass = new DFAPass(man);
+ pass->run();
+ pass->finish();
}
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
index 2ec0e44..2542a4e 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,104 +1,108 @@
#include "gtest/gtest.h"
#include "passmanager.h"
#include "Scanner.h"
#include "Parser.h"
#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
using namespace std;
-TEST(InterfaceExternC, testAST){
- std::string code = " \
+TEST(InterfaceExternC, testAST) {
+ std::string code = " \
interface(extern-c){ \
xml2 = library:: pkgconfig(\"libxml-2.0\"). \
\
include { \
xml2 = [\"libxml/tree.h\"] \
}. \
} \
";
- Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
+ Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(1, parser.root.__externdata.size());
- for (const ExternEntry& lib: parser.root.__externdata){
- ASSERT_EQ("libxml-2.0", lib.package);
- ASSERT_EQ(1, lib.headers.size());
- ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
+ for (const ExternEntry& lib : parser.root.__externdata) {
+ ASSERT_EQ("libxml-2.0", lib.package);
+ ASSERT_EQ(1, lib.headers.size());
+ ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
}
}
-TEST(InterfaceExternC, testfetchPackageHeaders){
- ExternEntry entry{"libxml-2.0", {}};
+TEST(InterfaceExternC, testfetchPackageHeaders) {
+ ExternEntry entry{"libxml-2.0",
+ {}};
- vector<string> args = ExternLayer::fetchPackageFlags(entry);
- ASSERT_EQ(1, args.size());
- ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
+ vector<string> args = ExternLayer::fetchPackageFlags(entry);
+ ASSERT_EQ(1, args.size());
+ ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
}
-TEST(InterfaceExternC, testfetchPackageLibs){
- ExternEntry entry{"libxml-2.0", {}};
+TEST(InterfaceExternC, testfetchPackageLibs) {
+ ExternEntry entry{"libxml-2.0",
+ {}};
- vector<string> args = ExternLayer::fetchPackageLibs(entry);
- ASSERT_EQ(1, args.size());
+ vector<string> args = ExternLayer::fetchPackageLibs(entry);
+ ASSERT_EQ(1, args.size());
ASSERT_EQ("xml2", args.at(0));
+
}
-TEST(InterfaceExternC, testLoadLib){
- std::string msgErr;
- if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)){
- cout << msgErr;
- ASSERT_EQ("", msgErr);
- }
+TEST(InterfaceExternC, testLoadLib) {
+ std::string msgErr;
+ if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)) {
+ cout << msgErr;
+ ASSERT_EQ("", msgErr);
+ }
- ASSERT_TRUE(true);
+ ASSERT_TRUE(true);
}
-TEST(InterfaceExternC, testBSD1){
- std::string code = " \n\
- interface(extern-c){ \n\
- libbsd = library:: pkgconfig(\"libbsd\"). \n\
- \n\
- include { \n\
- libbsd = [\"bsd/stdlib.h\"] \n\
- }. \n\
- }\n"
- "main= function():: int; entry{arc4random() }";
-
- std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
-
- void* entryPtr = program->run();
- int (*entry)() = (int (*)())(intptr_t)entryPtr;
-
- int answer = 24;
- answer = entry();
- cout << answer;
- ASSERT_NE(24, answer);
+TEST(InterfaceExternC, testBSD1) {
+ std::string code = " \n\
+ interface(extern-c){ \n\
+ libbsd = library:: pkgconfig(\"libbsd\"). \n\
+ \n\
+ include { \n\
+ libbsd = [\"bsd/stdlib.h\"] \n\
+ }. \n\
+ } \n"
+
+ "main= function:: int; entry{arc4random_uniform(24) }";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+
+ void* entryPtr = program->run();
+ int (*entry)() = (int (*)())(intptr_t) entryPtr;
+
+ int answer = 24;
+ answer = entry();
+ cout << answer;
+ ASSERT_LT(answer, 24);
}
-TEST(InterfaceExternC, testStructFields1){
- FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
- assert(input != nullptr);
+TEST(InterfaceExternC, testStructFields1) {
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate", "r");
+ assert(input != nullptr);
- Scanner scanner(input);
- Parser parser(&scanner);
- parser.Parse();
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
- AST& ast = parser.root;
- CodeScope* body = ast.findFunction("test")->getEntryScope();
+ AST& ast = parser.root;
+ CodeScope* body = ast.findFunction("test")->getEntryScope();
- Symbol symbTree = body->findSymbol("tree");
+ Symbol symbTree = body->findSymbol("tree");
const TypeAnnotation& tTree = CodeScope::findDeclaration(symbTree).type;
const ExpandedType& t2Tree = ast.expandType(tTree);
LLVMLayer llvm(&ast);
TypeUtils utils(&llvm);
std::vector<std::string>fields = utils.getStructFields(t2Tree);
auto field = std::find(fields.begin(), fields.end(), "children");
ASSERT_TRUE(field != fields.end());
}
diff --git a/cpp/tests/installation.cpp b/cpp/tests/installation.cpp
index dd2e1e2..19c48b8 100644
--- a/cpp/tests/installation.cpp
+++ b/cpp/tests/installation.cpp
@@ -1,22 +1,23 @@
/*
* 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){
+//TODO enable tests. Depends on context loop(test: Context.full_LoopContext)
+TEST(Sprint1, DISABLED_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/interpretation.cpp b/cpp/tests/interpretation.cpp
index d092f25..8cc549b 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,286 +1,352 @@
#include "attachments.h"
using namespace xreate;
#include "passmanager.h"
#include "compilation/targetinterpretation.h"
#include "gtest/gtest.h"
#include "boost/scoped_ptr.hpp"
#define private public
#include "Parser.h"
#include "pass/interpretationpass.h"
using namespace xreate;
using namespace xreate::compilation;
TEST(Interpretation, Analysis_StatementIF_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function::int {
x = "a":: string.
y = if (x=="b"):: string; interpretation(force) {
1
} else {
0
}.
y
}
)Code" );
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
Symbol symbolY = man->root->findFunction("main")->__entry->findSymbol("y");
InterpretationData& dataSymbolY = Attachments::get<Symbol, InterpretationData>(symbolY);
ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution);
}
TEST(Interpretation, Compilation_StatementIF_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function::int; entry {
x = "a":: string.
y = if (x=="b"):: string; interpretation(force) {
1
} else {
0
}.
y
}
)Code" );
man->runWithoutCompilation();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function::int {
x = "a":: string; interpretation(force).
y = if (x=="b"):: string {
1
} else {
0
}.
y
}
)Code" );
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
Symbol symbolY = man->root->findFunction("main")->__entry->findSymbol("y");
InterpretationData& dataSymbolY = Attachments::get<Symbol, InterpretationData>(symbolY);
- ASSERT_EQ(BOTH, dataSymbolY.resolution);
+ ASSERT_EQ(ANY, dataSymbolY.resolution);
ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
}
TEST(Interpretation, Compilation_StatementIF_InterpretCondition_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function::int; entry {
x = "a":: string; interpretation(force).
y = if (x=="b"):: string {
1
} else {
0
}.
y
}
)Code" );
man->runWithoutCompilation();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, Compilation_StatementFOLD_INTERPRET_INPUT_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function::int; entry {
commands = ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, 10->operand):: int{
switch(comm)::int
case ("inc"){
operand + 1
}
case ("dec"){
operand - 1
}
case ("double"){
operand * 2
}
}
}
)Code" );
man->runWithoutCompilation();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(21, result);
}
TEST(Interpretation, StatementCall_RecursionNo_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
unwrap = function(data::undef, keys::undef):: undef; interpretation(force){
loop fold(keys->key::string, data->a):: undef {
a[key]
}
}
start = function::num; entry{
result = unwrap(
{
a = {
b =
{
c = "core"
}
}
}, ["a", "b", "c"])::undef.
result == "core"
}
)Code" );
man->runWithoutCompilation();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(1, result);
}
TEST(Interpretation, StatementCall_RecursionDirect_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
unwrap = function(data:: X):: Y {
if (data[0] == "a")::Y {0} else {unwrap(data[0])}
}
entry = function:: i8; entry {
unwrap([[[["a"]]]]):: i8; interpretation(force)
}
)Code" );
man->runWithoutCompilation();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
InterpretationResolution resolutionActual = pass->process(man->root->findFunction("unwrap"));
- ASSERT_EQ(BOTH, resolutionActual);
+ ASSERT_EQ(ANY, resolutionActual);
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, StatementCall_RecursionIndirect_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
funcA = function(data:: X):: Y {
if (data == "a")::Y {0} else {funcB(data)}
}
funcB = function(data:: X):: Y {
if (data == "b")::Y {1} else {funcA(data)}
}
entry = function:: i8; entry {
funcA(""):: i8; interpretation(force)
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
ASSERT_DEATH(pass->run(), "Indirect recursion detected");
}
+TEST(Interpretation, PartialIntr_1){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
+ switch(code)::int
+ case ("inc") {argument + 1}
+ case ("dec") {argument - 1}
+ case ("double") {argument * 2}
+ }
+
+ main = function::int; entry {
+ commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
+
+ loop fold(commands->comm::string, 10->operand):: int{
+ evaluate(operand, comm)
+ }
+ }
+)Code" );
+
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
+
+ ManagedFnPtr fnEvaluate = man->root->findFunction("evaluate");
+ InterpretationResolution resFnEvaluate= pass->process(fnEvaluate);
+ ASSERT_EQ(CMPL_ONLY, resFnEvaluate);
+ ASSERT_TRUE(FunctionInterpretationHelper::needPartialInterpretation(fnEvaluate));
+
+ const Expression& exprLoop = man->root->findFunction("main")->__entry->getBody();
+ Symbol symbCallEv{0, exprLoop.blocks.front()};
+ InterpretationData dataCallEv = Attachments::get<Symbol, InterpretationData>(symbCallEv);
+ ASSERT_EQ(CMPL_ONLY, dataCallEv.resolution);
+ ASSERT_EQ(CALL_INTERPRET_PARTIAL, dataCallEv.op);
+}
+
+TEST(Interpretation, PartialIntr_2){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
+ switch(code)::int
+ case ("inc") {argument + 1}
+ case ("dec") {argument - 1}
+ case ("double") {argument * 2}
+ case default {argument}
+ }
+
+ main = function::int; entry {
+ commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
+
+ loop fold(commands->comm::string, 10->operand):: int{
+ evaluate(operand, comm)
+ }
+ }
+)Code" );
+
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+
+ ASSERT_EQ(21, result);
+}
+
//TOTEST call indirect recursion(w/o tags)
//TASK implement and test Loop Inf (fix acc types in coco grammar)
+
+
+
diff --git a/cpp/tests/loops.cpp b/cpp/tests/loops.cpp
index 7d1d5d7..efa66a5 100644
--- a/cpp/tests/loops.cpp
+++ b/cpp/tests/loops.cpp
@@ -1,59 +1,59 @@
#include "passmanager.h"
#include "gtest/gtest.h"
using namespace std;
TEST(Loop, Break1){
- string code =
+ string code =
R"CODE(
main = function:: int; entry {
input = [0..10]:: [int].
-
+
loop fold(input->el::int, 0->a)::[int]
{
if (a>=5)::int {
5:: int; break
-
+
} else {a+el}
}
}
-
+
)CODE";
-
+
xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
int (*funcMain)() = (int (*)()) man->run();
-
+
int answerActual = funcMain();
ASSERT_EQ(5, answerActual);
}
TEST(Loop, InfiniteLoop1){
-
- string code =
+
+ string code =
R"Code(
- interface(extern-c){
- libFake = library:: pkgconfig("libxml-2.0").
-
- include {
- libFake = ["math.h"]
- }.
+ fac = function(x:: int):: int{
+ range = [2..x] :: [int].
+
+ loop fold(range->i::int, 1->acc)::int {
+ acc * i
+ }
}
-
+
main = function:: int; entry {
- loop fold inf(0->state) :: int {
- if (pow(2, state)==32)::int {
+ loop fold inf(2->state) :: int {
+ if (fac(state)==120)::int {
state::int; break
-
+
} else {state + 1}
}
}
-
+
)Code" ;
-
+
xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
int (*funcMain)() = (int (*)()) man->run();
-
+
int answerActual = funcMain();
ASSERT_EQ(5, answerActual);
}
\ No newline at end of file
diff --git a/cpp/tests/pass-Logger.cpp b/cpp/tests/pass-Logger.cpp
index 46d4ba4..e74577b 100644
--- a/cpp/tests/pass-Logger.cpp
+++ b/cpp/tests/pass-Logger.cpp
@@ -1,85 +1,86 @@
/*
* 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"
using namespace std;
using namespace xreate;
-TEST(LoggerPass, simpleInjection){
+//TODO fix logger and enable tests.
+TEST(LoggerPass, DISABLED_simpleInjection){
PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");
man->runWithoutCompilation();
CompilePass* compiler = new CompilePass(man);
compiler->run();
compilation::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("test"));
ASSERT_NE(fTest, nullptr);
compilation::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
CodeScope* scopeTest = scopeUnitTest->scope;
Symbol symbX = scopeTest->findSymbol("x");
TypeAnnotation typX = CodeScope::findDeclaration(symbX).type;
llvm::Value* retRaw = scopeUnitTest->compile();
llvm::BasicBlock& blockTestRaw = fTest->raw->getEntryBlock();
LLVMLayer* llvm = man->llvm;
//llvm->builder.SetInsertPoint(&blockTestRaw);
compilation::Context params{scopeUnitTest, fTest, 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){
+TEST(LoggerPass, DISABLED_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){
+TEST(LoggerPass, DISABLED_simpleInjection3){
FILE* input = fopen("scripts/cases/log.xreate","r");
assert(input);
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/types.cpp b/cpp/tests/types.cpp
index 97e2354..d90a673 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,167 +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::findDeclaration(symb).type;
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::findDeclaration(symbTree).type;
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;
+ Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody();
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}"
+ " colors = type variant (RED, BLUE, GREEN). \n"
+ " test = function:: colors {GREEN} \n"
- "main = function:: int; entry {\n"
- " switch(test():: color)\n"
- " case GREEN {0}\n"
- " case default {1}\n"
+ "main = function:: int; entry { \n"
+ " switch(test()):: int \n"
+ " case GREEN {0} \n"
+ " case default {1} \n"
"}";
PassManager* man = PassManager::prepareForCode(move(code));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(0, main());
}
//TOTEST string type
diff --git a/cpp/tests/xml.cpp b/cpp/tests/xml.cpp
index 653f60e..13b312a 100644
--- a/cpp/tests/xml.cpp
+++ b/cpp/tests/xml.cpp
@@ -1,29 +1,29 @@
#include "passmanager.h"
#include "gtest/gtest.h"
#include <stdio.h>
using namespace xreate;
-TEST(Xml, Main){
+TEST(Xml, DISABLED_Main){
FILE* input = fopen("scripts/testspass/xml-test1.xreate", "r");
assert(input);
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/documentation-tools/RemarkupParser/CMakeLists.txt b/documentation-tools/RemarkupParser/CMakeLists.txt
index d2f6ef6..3ddbfbe 100644
--- a/documentation-tools/RemarkupParser/CMakeLists.txt
+++ b/documentation-tools/RemarkupParser/CMakeLists.txt
@@ -1,23 +1,23 @@
project(RemarkupParser)
aux_source_directory(cpp/ SRC_LIST)
set(SRC_LIST ${SRC_LIST}
gen-cpp/PhabricatorParserPrivate.cpp
gen-cpp/remarkup_constants.cpp
gen-cpp/remarkup_types.cpp
)
include_directories(cpp/ gen-cpp/)
set(REMARKUP_PARSER_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/cpp/
${CMAKE_CURRENT_SOURCE_DIR}/gen-cpp/
CACHE INTERNAL "REMARKUP_PARSER: Include Directories" FORCE
)
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
-target_link_libraries(${PROJECT_NAME} thrift-1.0.0-dev Qt5::Core)
+target_link_libraries(${PROJECT_NAME} thrift Qt5::Core)
set(CMAKE_BUILD_TYPE Debug)
diff --git a/documentation-tools/RemarkupParser/shared.thrift b/documentation-tools/RemarkupParser/shared.thrift
deleted file mode 100644
index 386000b..0000000
--- a/documentation-tools/RemarkupParser/shared.thrift
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * This Thrift file can be included by other Thrift files that want to share
- * these definitions.
- */
-
-namespace cpp shared
-namespace d share // "shared" would collide with the eponymous D keyword.
-namespace dart shared
-namespace java shared
-namespace perl shared
-namespace php shared
-namespace haxe shared
-
-struct SharedStruct {
- 1: i32 key
- 2: string value
-}
-
-service SharedService {
- SharedStruct getStruct(1: i32 key)
-}
diff --git a/documentation-tools/RemarkupParser/test/main.cpp b/documentation-tools/RemarkupParser/test/main.cpp
deleted file mode 100644
index 5361187..0000000
--- a/documentation-tools/RemarkupParser/test/main.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <iostream>
-
-#include <thrift/protocol/TBinaryProtocol.h>
-#include <thrift/transport/TSocket.h>
-#include <thrift/transport/TTransportUtils.h>
-
-#include "gen-cpp/PhabricatorParserPrivate.h"
-
-using namespace std;
-using namespace apache::thrift;
-using namespace apache::thrift::protocol;
-using namespace apache::thrift::transport;
-
-int main() {
- boost::shared_ptr<TTransport> socket(new TSocket("/tmp/phabricator-parser"));
- boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
- boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
- PhabricatorParserPrivateClient client(protocol);
-
- string text =
-"= Large Header = \n \
- \n\
-== Smaller Header == \n\
- \n\
-## This is a Header As Well\n\
- \n\
-Also a Large Header \n\
-=================== \n\
- \n\
-Also a Smaller Header \n\
----------------------";
- try {
- transport->open();
-
-
- for (int i=0; i<answer.size(); ++i){
- Block b = answer[i];
- cout << b.start << " " << b.num_lines << " " << b.rule << endl;
- }
-
- cout << answer.size();
-
- } catch (TException& tx) {
- cout << "ERROR: " << tx.what() << endl;
- }
-}
diff --git a/documentation-tools/RemarkupParser/tutorial.thrift b/documentation-tools/RemarkupParser/tutorial.thrift
deleted file mode 100644
index c4a96f0..0000000
--- a/documentation-tools/RemarkupParser/tutorial.thrift
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-# Thrift Tutorial
-# Mark Slee (mcslee@facebook.com)
-#
-# This file aims to teach you how to use Thrift, in a .thrift file. Neato. The
-# first thing to notice is that .thrift files support standard shell comments.
-# This lets you make your thrift file executable and include your Thrift build
-# step on the top line. And you can place comments like this anywhere you like.
-#
-# Before running this file, you will need to have installed the thrift compiler
-# into /usr/local/bin.
-
-/**
- * The first thing to know about are types. The available types in Thrift are:
- *
- * bool Boolean, one byte
- * i8 (byte) Signed 8-bit integer
- * i16 Signed 16-bit integer
- * i32 Signed 32-bit integer
- * i64 Signed 64-bit integer
- * double 64-bit floating point value
- * string String
- * binary Blob (byte array)
- * map<t1,t2> Map from one type to another
- * list<t1> Ordered list of one type
- * set<t1> Set of unique elements of one type
- *
- * Did you also notice that Thrift supports C style comments?
- */
-
-// Just in case you were wondering... yes. We support simple C comments too.
-
-/**
- * Thrift files can reference other Thrift files to include common struct
- * and service definitions. These are found using the current path, or by
- * searching relative to any paths specified with the -I compiler flag.
- *
- * Included objects are accessed using the name of the .thrift file as a
- * prefix. i.e. shared.SharedObject
- */
-include "shared.thrift"
-
-/**
- * Thrift files can namespace, package, or prefix their output in various
- * target languages.
- */
-namespace cpp tutorial
-namespace d tutorial
-namespace dart tutorial
-namespace java tutorial
-namespace php tutorial
-namespace perl tutorial
-namespace haxe tutorial
-
-/**
- * Thrift lets you do typedefs to get pretty names for your types. Standard
- * C style here.
- */
-typedef i32 MyInteger
-
-/**
- * Thrift also lets you define constants for use across languages. Complex
- * types and structs are specified using JSON notation.
- */
-const i32 INT32CONSTANT = 9853
-const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
-
-/**
- * You can define enums, which are just 32 bit integers. Values are optional
- * and start at 1 if not supplied, C style again.
- */
-enum Operation {
- ADD = 1,
- SUBTRACT = 2,
- MULTIPLY = 3,
- DIVIDE = 4
-}
-
-/**
- * Structs are the basic complex data structures. They are comprised of fields
- * which each have an integer identifier, a type, a symbolic name, and an
- * optional default value.
- *
- * Fields can be declared "optional", which ensures they will not be included
- * in the serialized output if they aren't set. Note that this requires some
- * manual management in some languages.
- */
-struct Work {
- 1: i32 num1 = 0,
- 2: i32 num2,
- 3: Operation op,
- 4: optional string comment,
-}
-
-/**
- * Structs can also be exceptions, if they are nasty.
- */
-exception InvalidOperation {
- 1: i32 whatOp,
- 2: string why
-}
-
-/**
- * Ahh, now onto the cool part, defining a service. Services just need a name
- * and can optionally inherit from another service using the extends keyword.
- */
-service Calculator extends shared.SharedService {
-
- /**
- * A method definition looks like C code. It has a return type, arguments,
- * and optionally a list of exceptions that it may throw. Note that argument
- * lists and exception lists are specified using the exact same syntax as
- * field lists in struct or exception definitions.
- */
-
- void ping(),
-
- i32 add(1:i32 num1, 2:i32 num2),
-
- i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
-
- /**
- * This method has a oneway modifier. That means the client only makes
- * a request and does not listen for any response at all. Oneway methods
- * must be void.
- */
- oneway void zip()
-
-}
-
-/**
- * That just about covers the basics. Take a look in the test/ folder for more
- * detailed examples. After you run this file, your generated code shows up
- * in folders with names gen-<language>. The generated code isn't too scary
- * to look at. It even has pretty indentation.
- */
diff --git a/documentation-tools/conduit-client-example.cpp b/documentation-tools/conduit-client-example.cpp
deleted file mode 100644
index 04bae68..0000000
--- a/documentation-tools/conduit-client-example.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <iostream>
-#include "phrictionclient.h"
-#include <QCoreApplication>
-
-using namespace std;
-
-int main(int argc, char** argv)
-{
- QCoreApplication a(argc, argv);
-
- PhrictionClient c("http://192.168.11.130:80/api", "user", "api-ko4x6j4hujleutuxlntdqj37wfjj", "bydxwfn7pey6ack274dilywrgakkhjpmwrgieedqxlnxpocwovisz3ysgndzagtmft33e2tx3xyatwklzbrrzhyyonibim7nwbnpqo36fmer7hjvv5mmmammxf3fybqn52dgsmczrj44e4l4r774ajyiydmcxughsttgonydjsgf3b2rmvtunjtez4zbtcqmwrhjl3aijv22jefvymu2oz3tzu3zlv4lk226riq5utudndd6ae4ixzqmzyo6pqr");
- c.create();
-
- return a.exec();
-}
-
diff --git a/documentation-tools/juffed-lexers/qscilexerremarkup.cpp b/documentation-tools/juffed-lexers/qscilexerremarkup.cpp
index 1e3c3b5..37f2e7e 100644
--- a/documentation-tools/juffed-lexers/qscilexerremarkup.cpp
+++ b/documentation-tools/juffed-lexers/qscilexerremarkup.cpp
@@ -1,171 +1,161 @@
#include "qscilexerremarkup.h"
#include <qsciscintilla.h>
#include <QRegularExpression>
-enum
- {
- Default = 0,
- Hidden,
- Bold,
- Italic,
- Del,
- DocumentLink,
- EscapeRemarkup,
- Hightlight,
- HyperLink,
-
- Monospace,
- Underline
- };
-
QRegularExpression patternBold("\\*\\*(.+?)\\*\\*");
QRegularExpression patternItalic("(?<!:)//(.+?)//");
const char*
QsciLexerRemarkup::language() const
{
return "Remarkup";
}
QString
QsciLexerRemarkup::description(int style) const
{
- switch(style){
- case Default:
- return "Default";
- case Bold:
- return "Bold";
- case Italic:
- return "Italic";
- case Hidden:
- return "Hidden";
- }
-
- return QString();
+ switch((QsciLexerRemarkupStyles) style){
+ case QsciLexerRemarkupStyles::Default:
+ return "Default";
+ case QsciLexerRemarkupStyles::Bold:
+ return "Bold";
+ case QsciLexerRemarkupStyles::Italic:
+ return "Italic";
+ case QsciLexerRemarkupStyles::Hidden:
+ return "Hidden";
+
+ default: break;
+ }
+
+ return QString();
}
QColor
QsciLexerRemarkup::defaultColor(int style) const
{
- switch(style){
- case Default:
+ switch((QsciLexerRemarkupStyles) style){
+ case QsciLexerRemarkupStyles::Default:
break;
- case Bold:
+ case QsciLexerRemarkupStyles::Bold:
return Qt::red;
+
+ default: break;
}
return QsciLexer::defaultColor();
}
QFont
QsciLexerRemarkup::defaultFont(int style) const
{
+ Q_UNUSED(style);
// QFont f = QsciLexer::defaultFont();
// switch(style){
// case Default:
// break;
// case Bold:
// f.setBold(true);
// f.setCapitalization(QFont::AllUppercase);
// break;
// }
// return f;
return QsciLexer::defaultFont();
}
QColor
QsciLexerRemarkup::defaultPaper(int style) const
{
+ Q_UNUSED(style);
return QsciLexer::defaultPaper();
}
QsciStyle
QsciLexerRemarkup::getStyle(int style)
{
return QsciStyle(style, description(style), defaultColor(style),
defaultPaper(style), defaultFont(style));
}
QsciLexerRemarkup::QsciLexerRemarkup(QObject * parent)
:QsciLexerCustom(parent)
{
}
QsciLexerRemarkup::~QsciLexerRemarkup()
{}
void
QsciLexerRemarkup::styleText(int start, int end){
if (!editor()) return;
if (start == end) return;
QsciScintilla* e = editor();
//reset styles:
startStyling(start);
- setStyling(end-start, Default);
+ setStyling(end-start, (int) QsciLexerRemarkupStyles::Default);
char * chars = new char[end - start + 1];
e->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, start, end, chars);
QString source = QString::fromUtf8(chars);
delete [] chars;
runPhutilRemarkupBoldRule(source,start);
runPhutilRemarkupItalicRule(source,start);
}
void
QsciLexerRemarkup::runPhutilRemarkupBoldRule(const QString& source, int index){
int pos =0;
while(true) {
QRegularExpressionMatch result = patternBold.match(source, pos);
if (!result.hasMatch()){break;}
//hide:
startStyling(index + result.capturedStart(0));
- setStyling(result.capturedLength(0), Hidden);
+ setStyling(result.capturedLength(0), (int) QsciLexerRemarkupStyles::Hidden);
QString r = result.captured(1);
startStyling(index + result.capturedStart(1));
- setStyling(result.capturedLength(1), Bold);
+ setStyling(result.capturedLength(1), (int) QsciLexerRemarkupStyles::Bold);
pos = result.capturedEnd(1) + 1;
}
}
void
QsciLexerRemarkup::runPhutilRemarkupItalicRule(const QString& source, int index){
int pos =0;
while(true) {
QRegularExpressionMatch result = patternItalic.match(source, pos);
if (!result.hasMatch()){break;}
//hide:
startStyling(index + result.capturedStart(0));
- setStyling(result.capturedLength(0), Hidden);
+ setStyling(result.capturedLength(0), (int) QsciLexerRemarkupStyles::Hidden);
startStyling(index + result.capturedStart(1));
- setStyling(result.capturedLength(1), Italic);
+ setStyling(result.capturedLength(1), (int) QsciLexerRemarkupStyles::Italic);
pos = result.capturedEnd(1) + 1;
}
}
//"PhutilRemarkupBoldRule.php: **bold**
//PhutilRemarkupItalicRule.php: //italic//
/*
"PhutilRemarkupDelRule.php"
"PhutilRemarkupDocumentLinkRule.php"
"PhutilRemarkupEscapeRemarkupRule.php"
"PhutilRemarkupHighlightRule.php"
"PhutilRemarkupHyperlinkRule.php"
"PhutilRemarkupLinebreaksRule.php"
"PhutilRemarkupMonospaceRule.php"
"PhutilRemarkupRule.php"
"PhutilRemarkupUnderlineRule.php"
*/
diff --git a/documentation-tools/juffed-lexers/qscilexerremarkup.h b/documentation-tools/juffed-lexers/qscilexerremarkup.h
index 597319d..f815777 100644
--- a/documentation-tools/juffed-lexers/qscilexerremarkup.h
+++ b/documentation-tools/juffed-lexers/qscilexerremarkup.h
@@ -1,29 +1,45 @@
#ifndef QSCILEXERREMARKUP_H
#define QSCILEXERREMARKUP_H
#include <qscilexercustom.h>
#include <qscistyle.h>
class QsciLexerRemarkup : public QsciLexerCustom
{
Q_OBJECT
public:
virtual QColor defaultColor(int style) const;
virtual QFont defaultFont(int style) const;
virtual QColor defaultPaper(int style) const;
QsciStyle getStyle(int style);
QsciLexerRemarkup(QObject * parent = 0);
~QsciLexerRemarkup();
void styleText(int start, int end);
QString description(int style) const;
const char* language() const;
private:
void runPhutilRemarkupBoldRule(const QString& source, int index);
void runPhutilRemarkupItalicRule(const QString& source, int index);
};
+enum class QsciLexerRemarkupStyles
+ {
+ Default = 0,
+ Hidden,
+ Bold,
+ Italic,
+ Del,
+ DocumentLink,
+ EscapeRemarkup,
+ Hightlight,
+ HyperLink,
+
+ Monospace,
+ Underline
+};
+
#endif // QSCILEXERREMARKUP_H
diff --git a/scripts/metatests/exploitation-test1.lp b/scripts/metatests/exploitation-test1.lp
deleted file mode 100644
index c217721..0000000
--- a/scripts/metatests/exploitation-test1.lp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "core/precompilation.lp".
-#include "core/exploitation.lp".
-
-#include "scripts/exploitation/test1-fixture.lp".
-
-#show bind/2.
-#show expl_sites/2.
-#show expl_resources/2.
-#show expl_parent/2.
-#show bind_scope/2.
diff --git a/scripts/metatests/tests1-context-latecontext3.lp b/scripts/metatests/tests1-context-latecontext3.lp
deleted file mode 100644
index f344ff0..0000000
--- a/scripts/metatests/tests1-context-latecontext3.lp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "core/control-context-v3.lp".
-function(a1;b1;a2;b2;a3;b3; sink; fnOut).
-scope(0..7).
-
- %CFA
-cfa_parent(0, function(a1)).
-cfa_parent(1, function(b1)).
-cfa_parent(2, function(a2)).
-cfa_parent(3, function(b2)).
-cfa_parent(4, function(a3)).
-cfa_parent(5, function(b3)).
-
-cfa_parent(6, function(sink)).
-cfa_parent(7, function(fnOut)).
-
-cfa_function_specializations(fnOut, keys(keyA1A2A3)).
-cfa_function_specializations(fnOut, keys(keyA1A2B3)).
-cfa_function_specializations(fnOut, keys(keyA1B2A3)).
-cfa_function_specializations(fnOut, keys(keyA1B2B3)).
-cfa_function_specializations(fnOut, keys(keyB1A2A3)).
-cfa_function_specializations(fnOut, keys(keyB1A2B3)).
-cfa_function_specializations(fnOut, keys(keyB1B2A3)).
-cfa_function_specializations(fnOut, keys(keyB1B2B3)).
-
-
-cfa_call(0, a2).
-cfa_call(0, b2).
-cfa_call(1, a2).
-cfa_call(1, b2).
-cfa_call(2, a3).
-cfa_call(2, b3).
-cfa_call(3, a3).
-cfa_call(3, b3).
-cfa_call(4, sink).
-cfa_call(5, sink).
-cfa_call(6, fnOut).
-
- %context rules
- % r0: keyA->keyA0, keyB->keyB0
- % r1: keyA->keyA1, keyB->keyB1
-bind_scope(2, keys(keyA1A2), Info) :- bind_scope(2, keys(keyA1), Info).
-bind_scope(2, keys(keyB1A2), Info) :- bind_scope(2, keys(keyB1), Info).
-bind_scope(3, keys(keyA1B2), Info) :- bind_scope(3, keys(keyA1), Info).
-bind_scope(3, keys(keyB1B2), Info) :- bind_scope(3, keys(keyB1), Info).
-
-bind_scope(4, keys(keyA1A2A3), Info):-bind_scope(4, keys(keyA1A2), Info).
-bind_scope(4, keys(keyB1A2A3), Info):-bind_scope(4, keys(keyB1A2), Info).
-bind_scope(4, keys(keyA1B2A3), Info):-bind_scope(4, keys(keyA1B2), Info).
-bind_scope(4, keys(keyB1B2A3), Info):-bind_scope(4, keys(keyB1B2), Info).
-
-bind_scope(5, keys(keyA1A2B3), Info):-bind_scope(5, keys(keyA1A2), Info).
-bind_scope(5, keys(keyB1A2B3), Info):-bind_scope(5, keys(keyB1A2), Info).
-bind_scope(5, keys(keyA1B2B3), Info):-bind_scope(5, keys(keyA1B2), Info).
-bind_scope(5, keys(keyB1B2B3), Info):-bind_scope(5, keys(keyB1B2), Info).
-
-
- %initial context
-keys(
- keyA1; keyB1;
- keyA1A2;
- keyB1A2;
- keyA1B2;
- keyB1B2;
- keyA1A2A3;
- keyA1A2B3;
- keyA1B2A3;
- keyA1B2B3;
- keyB1A2A3;
- keyB1A2B3;
- keyB1B2A3;
- keyB1B2B3
-).
-
-bind_scope(0, keys(keyA1), strong).
-bind_scope(1, keys(keyB1), strong).
diff --git a/scripts/sprint1_environment/(invalid)tests-context.lp b/scripts/sprint1_environment/(invalid)tests-context.lp
deleted file mode 100644
index 8559a15..0000000
--- a/scripts/sprint1_environment/(invalid)tests-context.lp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "control-context.lp".
-
-%body
- function(a).
- function(b).
- function(c).
-
- scope(0..3).
- cfa_call(0, c).
- cfa_call(1, c).
- cfa_parent(0, function(a)).
- cfa_parent(1, function(b)).
- cfa_parent(2, function(c)).
- cfa_parent(3, scope(2)).
-
- bind_scope(0, weak(a)).
- bind_scope(1, weak(b)).
-
- bind_scope(0, hard).
- bind_scope(1, hard).
-
-%test weak and hard context
- :- bind_scope(2, weak(_)).
- :- not bind_scope(2, hard).
-
-%test rules:
- bind_scope(X, rule) :- bind_scope(X, hard), context_rule_visibility(X, 2).
- :- not bind_scope(3, rule).
diff --git a/scripts/sprint1_environment/context-latecontext1.lp b/scripts/sprint1_environment/context-latecontext1.lp
deleted file mode 100644
index 536cdd3..0000000
--- a/scripts/sprint1_environment/context-latecontext1.lp
+++ /dev/null
@@ -1,26 +0,0 @@
-#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/sprint1_environment/context-latecontext2.lp b/scripts/sprint1_environment/context-latecontext2.lp
deleted file mode 100644
index b8c9195..0000000
--- a/scripts/sprint1_environment/context-latecontext2.lp
+++ /dev/null
@@ -1,67 +0,0 @@
-%#include "control-context.lp".
-
-function(a;b;c).
-scope(0..2).
-
- %general
-cfa_parent(0, function(a)).
-cfa_parent(1, function(b)).
-cfa_parent(2, function(c)).
-
-cfa_call(0, c).
-cfa_call(1, c).
-
- %additional
-keys(key0; key1).
-data(key0, x).
-data(key0, y).
-data(key1, m).
-data(key1, n).
-
-bind_scope(0, keys(key0), strong).
-bind_scope(1, keys(key1), strong).
-
-%bind_scope(0, a, strong).
-%bind_scope(0, b, strong).
-%bind_scope(1, a, strong).
-%bind_scope(1, c, strong).
-
-bind_scope(2, set(X), Options):- bind_scope(2, keys(Key), Options), data(Key, X).
-
- %nested scope propagation:
-bind_scope(Scope, Context, Info) :- bind_scope(ScopeParent, Context, Info), cfa_parent(Scope, scope(ScopeParent)).
-
- %strong inter-function propagation:
-bind_scope(Scope, Context,strong) :- bind_scope(ScopeParent, Context, strong): cfa_call(ScopeParent, FnCurrent); cfa_parent(Scope, function(FnCurrent)); cfa_call(_, FnCurrent); bind_scope(_, Context, strong); scope(Scope).
-
- %weak inter-function propagation
-bind_scope(Scope, Context, weak(ScopeParent)):- not bind_scope(Scope, Context, strong), bind_scope(ScopeParent, Context, strong), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
-bind_scope(Scope, Context, weak(Id)):- nbind_scope(Scope, Context, strong), bind_scope(ScopeParent, Context, weak(Id)), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
-
- %make decisions
-bind_scope_decision(Scope, loop(Subject), Scope):- cfa_contextloop(Scope, Subject), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).
-bind_scope_decision(Scope, loop(Subject), Scope):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, loop(Subject)), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).
-
- %demand
-% bind_scope_demand(Scope, loop(Subject)):- cfa_contextloop(Scope, Subject), not bind_scope_decision(Scope, loop(Subject), _).
-
- %nested scope demand propagation
-bind_scope_demand(Scope, Subject):- bind_scope_demand(ScopeChild, Subject), cfa_parent(ScopeChild, scope(Scope)).
-bind_function_demand(Fn, Subject):- bind_scope_demand(Scope, Subject), cfa_parent(Scope, function(Fn)).
-
- %inter-function propagation demand
-bind_scope_demand(Scope, Subject):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Subject), not bind_scope_decision(Scope, Subject, _).
-
-
-
-% GENERATED DECLARATIONS FOR DECISION DEPENDENCIES
-% -- cfa_contextloop(Scope, $set) => demand_dependency(loop(set), X) :- bind_scope($ScopeId, X = $set(_), weak(_)).
-demand_dependency(loop(set), X) :- bind_scope(2, X, weak(_)), X = set(_).
-
-% -- rule($Conditon, %Result) => demand_dependency(loop(X), $Condition) :- demand_dependency(loop(X), $Result)
-demand_dependency(loop(X), keys(Key)) :- demand_dependency(loop(X), set(Y)), bind_scope(_, keys(Key), _).
-
-
-cfa_contextloop(2, set).
-
-#show bind_scope/3.
diff --git a/scripts/sprint1_environment/context-latecontext3.lp b/scripts/sprint1_environment/context-latecontext3.lp
deleted file mode 100644
index ca81a77..0000000
--- a/scripts/sprint1_environment/context-latecontext3.lp
+++ /dev/null
@@ -1,48 +0,0 @@
- %% SCHEMA:
- %% specialization(Fn, Scope) - problem of what specialization of Fn should be picked up in Scope.
- %% resolution_dependency(Resolution, Dependency) - Dependency is necessary prerequisite for choosing Resolution.
- %%
-
- %nested scope propagation:
-bind_scope(Scope, Context, Info) :- bind_scope(ScopeParent, Context, Info), cfa_parent(Scope, scope(ScopeParent)).
-
- %strong/uniform inter-function propagation:
-bind_scope(Scope, Context,Info) :- bind_scope(ScopeParent, Context, Info): cfa_call(ScopeParent, FnCurrent); cfa_parent(Scope, function(FnCurrent)); cfa_call(_, FnCurrent); bind_scope(_, Context, Info); scope(Scope).
-
- %weak inter-function propagation
-bind_scope(Scope, Context, weak(ScopeParent)):- not bind_scope(Scope, Context, strong), bind_scope(ScopeParent, Context, strong), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
-bind_scope(Scope, Context, weak(ScopeParent, Info)):- Info<>strong, not bind_scope(Scope, Context, Info), bind_scope(ScopeParent, Context, Info), cfa_call(ScopeParent, FnCurrent), cfa_parent(Scope, function(FnCurrent)).
-
-
- %make decisions
-%%%bind_scope_decision(Scope, loop(Subject), Scope):- cfa_contextloop(Scope, Subject), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).*
-%%%bind_scope_decision(Scope, loop(Subject), Scope):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, loop(Subject)), demand_dependency(loop(Subject), X), bind_scope(Scope, X, strong).
-
- %on-site decision
-% ASSERT: ON-SITE DECISION SHOULD BE FIRST CLASS (checks at least one specialization exists)
-bind_scope_decision(Scope, Subject, Resolution):- bind_scope(Scope, Resolution, strong), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
-bind_scope_decision(ScopeSource, Subject, Resolution):- bind_scope(Scope, Resolution, weak(ScopeSource)), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
-bind_scope_decision(ScopeSource, Subject, resolution_dependency(Resolution, Dependency)):- bind_scope(Scope, Resolution, weak(ScopeSource, Dependency)), Subject = specialization(Fn, Scope), cfa_call(Scope, Fn), cfa_function_specializations(Fn, Resolution).
-
- %dependent decisions
-bind_scope_demand(Scope, dependency(Subject, Scope)) :- bind_scope_decision(Scope, Subject, resolution_dependency(_, Dependency)).
-
-bind_scope_decision(ScopeSource, dependency(Subject, Scope), Dependency) :- Dependency = weak(ScopeSource), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
-bind_scope_demand(ScopeSource, dependency(Subject, ScopeSource)) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
-
- %dependent decision helpers:
-scope_dependencies(dependency(Subject, Scope), Dependency) :- bind_scope_decision(Scope, Subject, resolution_dependency(_, Dependency)).
-scope_dependencies(dependency(Subject, ScopeSource), DependencyTail) :- Dependency = weak(ScopeSource, DependencyTail), bind_scope_demand(Scope, dependency(Subject, Scope)), scope_dependencies(dependency(Subject, Scope), Dependency).
-
- %on-site demand
-% ASSERT: ON-SITE DEMAND SHOULD BE dependent OF on-site decision (check there are no specializations AT ALL)
-%%%bind_scope_demand(Scope, Subject):- cfa_contextloop(Scope, Subject), not bind_scope_decision(Scope, loop(Subject), _).
-bind_scope_demand(Scope, Subject):- Subject = specialization(FnCallee, Scope), cfa_call(Scope, FnCallee), cfa_function_specializations(FnCallee, _), not bind_scope_decision(Scope, Subject, _).
-
- %nested scope demand propagation
-%ASSERT: NO DECISION CHECKS. because decisions linked to a leaf(function execution sites) scopes
-bind_scope_demand(Scope, Subject):- bind_scope_demand(ScopeChild, Subject), cfa_parent(ScopeChild, scope(Scope)).
-bind_function_demand(Fn, Subject):- bind_scope_demand(Scope, Subject), cfa_parent(Scope, function(Fn)).
-
- %inter-function propagation demand
-bind_scope_demand(Scope, Subject):- cfa_call(Scope, FnChild), bind_function_demand(FnChild, Subject), not bind_scope_decision(Scope, Subject, _).
diff --git a/scripts/sprint1_environment/control-context.lp b/scripts/sprint1_environment/control-context.lp
deleted file mode 120000
index 86bd292..0000000
--- a/scripts/sprint1_environment/control-context.lp
+++ /dev/null
@@ -1 +0,0 @@
-/private/prg/code/xreate/core/control-context.lp
\ No newline at end of file
diff --git a/scripts/sprint1_environment/dependencies.lp b/scripts/sprint1_environment/dependencies.lp
deleted file mode 120000
index 5d00940..0000000
--- a/scripts/sprint1_environment/dependencies.lp
+++ /dev/null
@@ -1 +0,0 @@
-/private/prg/code/xreate/core/graphs_trees_depth.lp
\ No newline at end of file
diff --git a/scripts/sprint1_environment/solution-latecontext-3layers b/scripts/sprint1_environment/solution-latecontext-3layers
deleted file mode 100644
index 2d13d91..0000000
--- a/scripts/sprint1_environment/solution-latecontext-3layers
+++ /dev/null
@@ -1,192 +0,0 @@
-
-bind_function_demand(a2,dependency(dependency(specialization(fnOut,6),4),2))
-bind_function_demand(a2,dependency(dependency(specialization(fnOut,6),5),2))
-bind_function_demand(a2,dependency(specialization(fnOut,6),2))
-bind_function_demand(a3,dependency(specialization(fnOut,6),4))
-bind_function_demand(b2,dependency(dependency(specialization(fnOut,6),4),3))
-bind_function_demand(b2,dependency(dependency(specialization(fnOut,6),5),3))
-bind_function_demand(b2,dependency(specialization(fnOut,6),3))
-bind_function_demand(b3,dependency(specialization(fnOut,6),5))
-bind_function_demand(sink,specialization(fnOut,6))
-
-bind_scope_demand(2,dependency(dependency(specialization(fnOut,6),4),2))
-bind_scope_demand(2,dependency(dependency(specialization(fnOut,6),5),2))
-bind_scope_demand(2,dependency(specialization(fnOut,6),2))
-bind_scope_demand(3,dependency(dependency(specialization(fnOut,6),4),3))
-bind_scope_demand(3,dependency(dependency(specialization(fnOut,6),5),3))
-bind_scope_demand(3,dependency(specialization(fnOut,6),3))
-bind_scope_demand(4,dependency(specialization(fnOut,6),4))
-bind_scope_demand(5,dependency(specialization(fnOut,6),5))
-bind_scope_demand(6,specialization(fnOut,6))
-
-bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),4),2),weak(0))
-bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),4),3),weak(0))
-bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),5),2),weak(0))
-bind_scope_decision(0,dependency(dependency(specialization(fnOut,6),5),3),weak(0))
-bind_scope_decision(0,dependency(specialization(fnOut,6),2),weak(0))
-bind_scope_decision(0,dependency(specialization(fnOut,6),3),weak(0))
-bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),4),2),weak(1))
-bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),4),3),weak(1))
-bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),5),2),weak(1))
-bind_scope_decision(1,dependency(dependency(specialization(fnOut,6),5),3),weak(1))
-bind_scope_decision(1,dependency(specialization(fnOut,6),2),weak(1))
-bind_scope_decision(1,dependency(specialization(fnOut,6),3),weak(1))
-bind_scope_decision(2,dependency(specialization(fnOut,6),4),resolution_dependency(weak(2,weak(0)),weak(0)))
-bind_scope_decision(2,dependency(specialization(fnOut,6),4),resolution_dependency(weak(2,weak(1)),weak(1)))
-bind_scope_decision(2,dependency(specialization(fnOut,6),5),resolution_dependency(weak(2,weak(0)),weak(0)))
-bind_scope_decision(2,dependency(specialization(fnOut,6),5),resolution_dependency(weak(2,weak(1)),weak(1)))
-bind_scope_decision(3,dependency(specialization(fnOut,6),4),resolution_dependency(weak(3,weak(0)),weak(0)))
-bind_scope_decision(3,dependency(specialization(fnOut,6),4),resolution_dependency(weak(3,weak(1)),weak(1)))
-bind_scope_decision(3,dependency(specialization(fnOut,6),5),resolution_dependency(weak(3,weak(0)),weak(0)))
-bind_scope_decision(3,dependency(specialization(fnOut,6),5),resolution_dependency(weak(3,weak(1)),weak(1)))
-bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyA1A2A3),weak(2,weak(0))))
-bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyA1B2A3),weak(3,weak(0))))
-bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyB1A2A3),weak(2,weak(1))))
-bind_scope_decision(4,specialization(fnOut,6),resolution_dependency(keys(keyB1B2A3),weak(3,weak(1))))
-bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyA1A2B3),weak(2,weak(0))))
-bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyA1B2B3),weak(3,weak(0))))
-bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyB1A2B3),weak(2,weak(1))))
-bind_scope_decision(5,specialization(fnOut,6),resolution_dependency(keys(keyB1B2B3),weak(3,weak(1))))
-
-scope_dependencies(dependency(dependency(specialization(fnOut,6),4),2),weak(0))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),4),2),weak(1))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),4),3),weak(0))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),4),3),weak(1))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),5),2),weak(0))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),5),2),weak(1))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),5),3),weak(0))
-scope_dependencies(dependency(dependency(specialization(fnOut,6),5),3),weak(1))
-scope_dependencies(dependency(specialization(fnOut,6),2),weak(0))
-scope_dependencies(dependency(specialization(fnOut,6),2),weak(1))
-scope_dependencies(dependency(specialization(fnOut,6),3),weak(0))
-scope_dependencies(dependency(specialization(fnOut,6),3),weak(1))
-scope_dependencies(dependency(specialization(fnOut,6),4),weak(2,weak(0)))
-scope_dependencies(dependency(specialization(fnOut,6),4),weak(2,weak(1)))
-scope_dependencies(dependency(specialization(fnOut,6),4),weak(3,weak(0)))
-scope_dependencies(dependency(specialization(fnOut,6),4),weak(3,weak(1)))
-scope_dependencies(dependency(specialization(fnOut,6),5),weak(2,weak(0)))
-scope_dependencies(dependency(specialization(fnOut,6),5),weak(2,weak(1)))
-scope_dependencies(dependency(specialization(fnOut,6),5),weak(3,weak(0)))
-scope_dependencies(dependency(specialization(fnOut,6),5),weak(3,weak(1)))
-
-bind_scope(0,keys(keyA1),strong)
-bind_scope(1,keys(keyB1),strong)
-bind_scope(2,keys(keyA1),weak(0))
-bind_scope(2,keys(keyA1A2),weak(0))
-bind_scope(2,keys(keyB1),weak(1))
-bind_scope(2,keys(keyB1A2),weak(1))
-bind_scope(3,keys(keyA1),weak(0))
-bind_scope(3,keys(keyA1B2),weak(0))
-bind_scope(3,keys(keyB1),weak(1))
-bind_scope(3,keys(keyB1B2),weak(1))
-bind_scope(4,keys(keyA1),weak(0))
-bind_scope(4,keys(keyA1A2),weak(2,weak(0)))
-bind_scope(4,keys(keyA1A2A3),weak(2,weak(0)))
-bind_scope(4,keys(keyA1B2),weak(3,weak(0)))
-bind_scope(4,keys(keyA1B2A3),weak(3,weak(0)))
-bind_scope(4,keys(keyB1),weak(1))
-bind_scope(4,keys(keyB1A2),weak(2,weak(1)))
-bind_scope(4,keys(keyB1A2A3),weak(2,weak(1)))
-bind_scope(4,keys(keyB1B2),weak(3,weak(1)))
-bind_scope(4,keys(keyB1B2A3),weak(3,weak(1)))
-bind_scope(5,keys(keyA1),weak(0))
-bind_scope(5,keys(keyA1A2),weak(2,weak(0)))
-bind_scope(5,keys(keyA1A2B3),weak(2,weak(0)))
-bind_scope(5,keys(keyA1B2),weak(3,weak(0)))
-bind_scope(5,keys(keyA1B2B3),weak(3,weak(0)))
-bind_scope(5,keys(keyB1),weak(1))
-bind_scope(5,keys(keyB1A2),weak(2,weak(1)))
-bind_scope(5,keys(keyB1A2B3),weak(2,weak(1)))
-bind_scope(5,keys(keyB1B2),weak(3,weak(1)))
-bind_scope(5,keys(keyB1B2B3),weak(3,weak(1)))
-bind_scope(6,keys(keyA1),weak(0))
-bind_scope(6,keys(keyA1A2),weak(2,weak(0)))
-bind_scope(6,keys(keyA1A2A3),weak(4,weak(2,weak(0))))
-bind_scope(6,keys(keyA1A2B3),weak(5,weak(2,weak(0))))
-bind_scope(6,keys(keyA1B2),weak(3,weak(0)))
-bind_scope(6,keys(keyA1B2A3),weak(4,weak(3,weak(0))))
-bind_scope(6,keys(keyA1B2B3),weak(5,weak(3,weak(0))))
-bind_scope(6,keys(keyB1),weak(1))
-bind_scope(6,keys(keyB1A2),weak(2,weak(1)))
-bind_scope(6,keys(keyB1A2A3),weak(4,weak(2,weak(1))))
-bind_scope(6,keys(keyB1A2B3),weak(5,weak(2,weak(1))))
-bind_scope(6,keys(keyB1B2),weak(3,weak(1)))
-bind_scope(6,keys(keyB1B2A3),weak(4,weak(3,weak(1))))
-bind_scope(6,keys(keyB1B2B3),weak(5,weak(3,weak(1))))
-bind_scope(7,keys(keyA1),weak(0))
-bind_scope(7,keys(keyA1A2),weak(2,weak(0)))
-bind_scope(7,keys(keyA1A2A3),weak(4,weak(2,weak(0))))
-bind_scope(7,keys(keyA1A2B3),weak(5,weak(2,weak(0))))
-bind_scope(7,keys(keyA1B2),weak(3,weak(0)))
-bind_scope(7,keys(keyA1B2A3),weak(4,weak(3,weak(0))))
-bind_scope(7,keys(keyA1B2B3),weak(5,weak(3,weak(0))))
-bind_scope(7,keys(keyB1),weak(1))
-bind_scope(7,keys(keyB1A2),weak(2,weak(1)))
-bind_scope(7,keys(keyB1A2A3),weak(4,weak(2,weak(1))))
-bind_scope(7,keys(keyB1A2B3),weak(5,weak(2,weak(1))))
-bind_scope(7,keys(keyB1B2),weak(3,weak(1)))
-bind_scope(7,keys(keyB1B2A3),weak(4,weak(3,weak(1))))
-bind_scope(7,keys(keyB1B2B3),weak(5,weak(3,weak(1))))
-
-
-
-
-cfa_call(0,a2)
-cfa_call(0,b2)
-cfa_call(1,a2)
-cfa_call(1,b2)
-cfa_call(2,a3)
-cfa_call(2,b3)
-cfa_call(3,a3)
-cfa_call(3,b3)
-cfa_call(4,sink)
-cfa_call(5,sink)
-cfa_call(6,fnOut)
-cfa_function_specializations(fnOut,keys(keyA1A2A3))
-cfa_function_specializations(fnOut,keys(keyA1A2B3))
-cfa_function_specializations(fnOut,keys(keyA1B2A3))
-cfa_function_specializations(fnOut,keys(keyA1B2B3))
-cfa_function_specializations(fnOut,keys(keyB1A2A3))
-cfa_function_specializations(fnOut,keys(keyB1A2B3))
-cfa_function_specializations(fnOut,keys(keyB1B2A3))
-cfa_function_specializations(fnOut,keys(keyB1B2B3))
-cfa_parent(0,function(a1))
-cfa_parent(1,function(b1))
-cfa_parent(2,function(a2))
-cfa_parent(3,function(b2))
-cfa_parent(4,function(a3))
-cfa_parent(5,function(b3))
-cfa_parent(6,function(sink))
-cfa_parent(7,function(fnOut))
-function(a1)
-function(a2)
-function(a3)
-function(b1)
-function(b2)
-function(b3)
-function(fnOut)
-function(sink)
-keys(keyA1)
-keys(keyA1A2)
-keys(keyA1A2A3)
-keys(keyA1A2B3)
-keys(keyA1B2)
-keys(keyA1B2A3)
-keys(keyA1B2B3)
-keys(keyB1)
-keys(keyB1A2)
-keys(keyB1A2A3)
-keys(keyB1A2B3)
-keys(keyB1B2)
-keys(keyB1B2A3)
-keys(keyB1B2B3)
-scope(0)
-scope(1)
-scope(2)
-scope(3)
-scope(4)
-scope(5)
-scope(6)
-scope(7)
-
-true
\ No newline at end of file
diff --git a/scripts/sprint1_environment/tests1-context-latecontext3.lp b/scripts/sprint1_environment/tests1-context-latecontext3.lp
deleted file mode 120000
index c21293f..0000000
--- a/scripts/sprint1_environment/tests1-context-latecontext3.lp
+++ /dev/null
@@ -1 +0,0 @@
-/private/prg/code/xreate/scripts/metatests/tests1-context-latecontext3.lp
\ No newline at end of file
diff --git a/scripts/testspass/Containers_Implementation_LinkedList1.xreate b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
index 7721ddc..2966ef4 100644
--- a/scripts/testspass/Containers_Implementation_LinkedList1.xreate
+++ b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
@@ -1,47 +1,47 @@
// EXTERN INCLUDES
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["libxml/tree.h"]
}.
}
// CONTAINERS
interface(dfa) {
operator map:: (op(seqaccess)) -> impl(solid).
operator list_range:: ()->impl(on_the_fly).
operator list:: ()->impl(solid).
operator fold:: (op(seqaccess)).
operator index:: (op(randaccess)).
/* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
}
import raw("core/containers.lp")
// 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.
+ filename = "scripts/testspass/Containers_Implementation_LinkedList1-data.xml" :: 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 {
+ size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count):: int {
count +1::int
}.
size
}
diff --git a/scripts/testspass/xml-test1.xreate b/scripts/testspass/xml-test1.xreate
index e763d7f..f5388c9 100644
--- a/scripts/testspass/xml-test1.xreate
+++ b/scripts/testspass/xml-test1.xreate
@@ -1,142 +1,142 @@
/* C++ SECTION
Example of c++ code:
xmlDocPtr doc;
xmlNodePtr cur;
doc = xmlParseFile(docname.c_str());
if (doc == NULL ) {
fprintf(stderr,"Document not parsed successfully. \n");
return;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
printf("child: %s\n", cur->name);
cur = cur->next;
}
*/
/* FEATURES SECTION
Default strategies:
- what to do with unspecified nodes
Node content strategy:
- send as-is
- apply transforms (all / named)
- ?? skip
Processing order:
- dependencies
Mapping:
* tree -> list
*/
/* TODO SECTION
-- gather types aliases (tree->list mapping)
-- flyweight implementation ('doc' field calculation, for example. based on are there more than one opened document )
*/
// REQUIREMENTS SECTION
/* require ptrvalid */
/* local scope doc ptr */
/* singleton element check(::single) */
XmlAttr = type alias {
name:: string,
content:: string
}.
XmlNode = type alias {
name:: string, /* the name of the node, or the entity */
content:: string, /* the content */
attributes::[XmlAttr] /* properties list */
/*
children:: [xmlNode], // parent->childs link
void *_private; // application data
struct _xmlNode *parent; // child->parent link
struct _xmlNode *next; // next sibling link
struct _xmlNode *prev; // previous sibling link
struct _xmlDoc *doc; // the containing document
unsigned short line; // line number
*/
}.
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["libxml/tree.h", "string.h"]
}.
}
Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
XmlTree = type alias Tree(XmlNode).
toXmlNode = function (nodeRaw:: xmlNodePtr):: XmlNode
{
propertiesRaw = nodeRaw["properties"]:: [xmlAttrPtr]; containers:linkedlist(next, null).
properties = loop map(propertiesRaw -> property::xmlAttrPtr)::[XmlAttr]{
{name=property["name"], content=property["children", "content"]}
}.
{name = nodeRaw["name"],
content=nodeRaw["content"],
attributes=properties}
}
children = function(nodeRaw::xmlDocPtr)::[XmlTree] {
childrenRaw = nodeRaw["children"]:: [xmlDocPtr]; containers:linkedlist(next, null).
children = loop map(childrenRaw->child:: xmlDocPtr) :: [XmlTree]{
[toXmlNode(child), children(child)]
}.
children
}
document = function (filename:: string):: XmlTree
{
docRaw = xmlParseFile(filename) :: xmlDocPtr.
nodeRaw= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
[toXmlNode(nodeRaw), children(nodeRaw)]:: XmlTree
}
traverse = function(tree:: XmlTree) :: [XmlNode] {
- listOfNodes = loop fold(tree -> node:: XmlTree, []->acc:: [XmlNode]):: [XmlNode]{
+ listOfNodes = loop fold(tree -> node:: XmlTree, []->acc):: [XmlNode]{
acc + node[0] + traverse(node[1]):: [XmlNode]
}.
listOfNodes
}
-test1 = function():: int; entry {
+test1 = function:: int; entry {
filename = "project/documentation.fodt" :: string.
root = document(filename):: XmlTree.
nodesAll = traverse(root):: [XmlNode].
- result = loop fold(nodesAll->node:: XmlNode, 0->count::int):: int{
+ result = loop fold(nodesAll->node:: XmlNode, 0->count):: int{
count + if (0==strcmp(node["name"], "section")) :: int {
1
} else {
0
}
}.
result
}
diff --git a/tools/phabricator/administration/docker-compose.yml b/tools/phabricator/administration/docker-compose.yml
new file mode 100644
index 0000000..caf839f
--- /dev/null
+++ b/tools/phabricator/administration/docker-compose.yml
@@ -0,0 +1,28 @@
+version: '2'
+
+services:
+ mariadb:
+ image: bitnami/mariadb:latest
+ volumes:
+ - mariadb_data:/bitnami/mariadb
+ phabricator:
+ image: bitnami/phabricator:latest
+ depends_on:
+ - mariadb
+ ports:
+ - '1001:80'
+ - '1002:443'
+ environment:
+ - PHABRICATOR_USERNAME='admin'
+ - PHABRICATOR_PASSWORD='phabricator-1'
+ volumes:
+ - phabricator_data:/bitnami/phabricator
+ - apache_data:/bitnami/apache
+
+volumes:
+ mariadb_data:
+ driver: local
+ phabricator_data:
+ driver: local
+ apache_data:
+ driver: local

Event Timeline