No OneTemporary

File Metadata

Created
Sun, Dec 22, 3:53 PM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.gitignore b/.gitignore
index 870c5b5..672d37a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,91 +1,81 @@
# 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
CMakeLists.txt.user
cmake_install.cmake
project/*
nb*.xml
.*
target/*
/tools/phabricator/xreate-frontend/nbproject/private/
documentation/trash4/
trash/
CMakeFiles/
gen-cpp/
generated-cpp/
gen-php/
generated-js/
books/
build/
coco/Parser.*
coco/Scanner.*
-cpp/src/compilation/latecontextcompiler.cpp
-cpp/src/compilation/latecontextcompiler.h
-cpp/src/pass/environmenttestspass.cpp
-cpp/src/pass/environmenttestspass.h
-cpp/src/query/ptrvalid.cpp
-cpp/src/query/ptrvalid.h
-cpp/tests/deferred/
-cpp/tests/vendorAPI/
-
-scripts/metatests/
tools/phabricator/administration/
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index 61a41af..b50fb1b 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,550 +1,599 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.h"
+#include "pass/adhocpass.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 nextToken()
{
- int kind = 0;
scanner->ResetPeek();
- while ((kind = scanner->Peek()->kind) == _colon)
- if (scanner->Peek()->kind != _ident)
- return 0;
-
- return kind;
+ return scanner->Peek()->kind;
}
bool checkParametersList()
{
- return la->kind == _ident && skipIdent() == _lparen;
+ return la->kind == _ident && nextToken() == _lparen;
}
bool checkInfix()
{
- return la->kind == _ident && skipIdent() == _ident;
+ return la->kind == _ident && nextToken() == _ident;
}
bool checkIndex()
{
- return la->kind == _ident && skipIdent() == _lbrack;
+ return la->kind == _ident && nextToken() == _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);
+ int token2 = nextToken();
+ int token3 = scanner->Peek()->kind;
+
+ return token2 == _assign && (token3 == _function || token3 == _pre);
}
bool checkAssignment()
{
+ if (la->kind != _ident) return false;
+
scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _assign;
+ int token2 = scanner->Peek()->kind;
+ if (token2 == _lcurbrack) {
+ scanner->Peek();
+ int token3 = scanner->Peek()->kind;
+ if (token3 != _rcurbrack) return false;
+
+ int token4 = scanner->Peek()->kind;
+ return token4 == _assign;
+ }
+
+ return token2 == _assign;
+}
+
+void recognizeIdentifier(Expression& i){
+ if (!context.scope->recognizeIdentifier(i)){
+ if (!root.recognizeVariantIdentifier(i)){
+ root.postponeIdentifier(context.scope, i);
+ }
+ }
}
+enum SwitchKind{SWITCH_NORMAL, SWITCH_META};
+
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
+{( RuleDecl
+ | InterfaceData | Imprt | ContextSection
| IF(checkFuncDecl()) FDecl<function> (. root.add(function); .)
- | TDecl ) }.
+ | TDecl
+)} (. root.recognizePostponedIdentifiers(); .)
+.
Ident<std::wstring& name>
-= ident {':' ident} (. name = t->val; .).
+= ident (. name = t->val; .).
+
+VarIdent<Expression& e>
+= ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
+ [ lcurbrack (
+ ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .)
+ | number (. Attachments::put<VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
+ ) rcurbrack ] .
+
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<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); .)
+ | Type<typOut>
)
{';' FnTag<f> }]
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" | "num" | "int" | "i8" | "i32" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .)
-.
+TypeTerm<TypePrimitive& typ> = (. std::wstring tid; .)
+ ("string" (. typ = TypePrimitive::String;.)
+ | "num" (. typ = TypePrimitive::Num;.)
+ | "int" (. typ = TypePrimitive::Int;.)
+ | "float" (. typ = TypePrimitive::Float;.)
+ | "bool" (. typ = TypePrimitive::Bool; .)
+ | "i8" (. typ = TypePrimitive::I8; .)
+ | "i32" (. typ = TypePrimitive::I32; .)
+ ).
-Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; std::wstring tid, field; .)
+Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
-| TypeTerm<typ3> (. typ = TypeAnnotation(typ3); .)
-|IF (checkIndex()) Ident<tid> lbrack
+| TypeTerm<typ3> (. typ = 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; .)
- '{'
+ lcurbrack
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()); .)
- '}'.
+ rcurbrack.
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;.)
-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(tag); .)
{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
+VDecl<CodeScope* f> = (. std::wstring vname; Expression var, value;.)
+ VarIdent<var> assign ExprTyped<value> (. f->addDeclaration(move(var), move(value)); .)
+.
+
//TODO forbid multiple body declaration (ExprTyped)
-BDecl<CodeScope* scope> = '{' (. Expression body; pushContextScope(scope);
- .)
- { (RuleContextDecl<scope> | ContextDecl<scope> '.'
- | IF(checkAssignment()) VDecl<scope> '.'
- | ExprTyped<body> (. scope->setBody(body); popContextScope();.)
-)} '}'.
+BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); .)
+ {(IF(checkAssignment()) VDecl<scope> '.'
+ | RuleContextDecl<scope>
+ | ContextDecl<scope>'.'
+ | ExprTyped<body> (. scope->setBody(body); .)
+ )} (. popContextScope(); .)
+ rcurbrack .
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> =
(. 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> (. e = Expression(Operator::MAP, {eIn}); .)
tagcolon ExprAnnotations<tagsEl> ')' tagcolon ExprAnnotations<e> BDecl<&*block>
(.
e.addBindings({Atom<Identifier_t>(varEl)});
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;.)
+SwitchDecl<Expression& eSwitch, SwitchKind flagSwitchKind> = (. 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)); .)
+ ( "ad" "hoc" lparen Expr<eCondition> tagcolon MetaSimpExpr<tag> rparen (. eSwitch.op = Operator::SWITCH_ADHOC;
+ eSwitch.operands.push_back(eCondition);
+ eSwitch.addTags({tag});
+ flagSwitchKind = SWITCH_META; .)
| lparen Expr<eCondition> rparen tagcolon ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
)
]
- CaseDecl<eSwitch> {CaseDecl<eSwitch>}
+ CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
.
-CaseDecl<Expression& outer> = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); .)
+CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); Expression condition; .)
"case"
- ( "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
+ ( IF(flagSwitchKind == SWITCH_META)
+ lparen MetaSimpExpr<condition> rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.)
+
+ | "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)); .)
+ | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
+ BDecl<&*scopeBody> (. 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> = (. Expression condition; .)
- (
- IF(checkAssignment()) VDecl<scope>
- | ExprTyped<condition> (. guard.addArg(move(condition)); .)
- ).
-
-SequenceDecl<Expression& sequence> =
-"sequence" ListLiteral<sequence> (. sequence.setOp(Operator::SEQUENCE); .).
+CaseParams<CodeScope* scope> = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
+ ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
+ {',' ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
+ } (. scope->setBody(guard); popContextScope(); .)
+.
+IntrinsicDecl<Expression& outer>= (. std::wstring name; .)
+"intrinsic" Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom<Identifier_t>(name)); .)
+lparen [CalleeParams<outer>] rparen .
/*============================ 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 } '}'.
PrefunctionSchemeDecl<> = (. TypeAnnotation typReturn; std::wstring prefName; Expression exprCases; .)
pre function Ident<prefName> tagcolon Type<typReturn>
- '{' SwitchDecl<exprCases> '}'
+ lcurbrack SwitchDecl<exprCases, SWITCH_META> rcurbrack
(. Expression prefData(Operator::CALL, {Atom<Identifier_t>(prefName), exprCases});
- prefData.type = typReturn;
+ prefData.bindType(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>
+"case" lparen MetaSimpExpr<eGuards> rparen
'{' 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> ] ')'
+'(' [ MetaCalleeParams<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)); .)
).
+MetaCalleeParams<Expression& e> = (. Expression e2; .)
+ MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
+ {',' MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
+ }.
+
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 ===============================*/
-ExprAnnotations<Expression& e> = (. TypeAnnotation typ; Expression tag; e.tags.clear();.)
+ExprAnnotations<Expression& e> = (. TypeAnnotation typ; std::list<Expression> tags; Expression tag; e.tags.clear();.)
Type<typ> (. e.bindType(move(typ)); .)
- {';' MetaSimpExpr<tag> (. e.tags.emplace(tag.getValueString(), tag); .)
- }.
+ {';' MetaSimpExpr<tag> (. tags.push_back(tag); .)
+ } (. e.addTags(tags); .)
+.
ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
Expr< Expression& e> (. Operator op; Expression e2; .)
-= SimExpr<e>
+= ExprArithmAdd<e>
[ RelOp<op>
-SimExpr<e2> (. e = Expression(op, {e, e2}); .)
+ ExprArithmAdd<e2> (. e = Expression(op, {e, e2}); .)
].
-SimExpr< Expression& e> (. Operator op; Expression e2; .)
-= Term< e>
- { AddOp< op>
- Term< e2> (. e = Expression(op, {e, e2});.)
- }.
+ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .)
+ ExprArithmMul< e>
+ [ AddOp< op>
+ ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
+ ].
-Term< Expression& e> (. Operator op; Expression e2; .)
-= Factor< e>
- { MulOp< op>
- Factor< e2> (. e = Expression(op, {e, e2}); .)
- }.
+ExprArithmMul< Expression& e> (. Operator op; Expression e2; .)
+= ExprPostfix< e>
+ [ MulOp< op>
+ ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .)
+ ].
-Factor< Expression& e> (. std::wstring name; e = Expression(); .)
+ExprPostfix<Expression& e>
+= Term<e>
+ [lbrack (. e = Expression(Operator::INDEX, {e}); .)
+ CalleeParams<e> rbrack
+ ].
+
+
+Term< 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); .)
+ | VarIdent<e> (. recognizeIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
- | SequenceDecl<e>
| LoopDecl<e>
- | IfDecl<e>
- | SwitchDecl<e>
+ | IfDecl<e>
+ | SwitchDecl<e, SWITCH_NORMAL>
| AdhocDecl<e>
-
+ | IntrinsicDecl<e>
+ | "true" (. e = Expression(Atom<Number_t>(1)); e.bindType(TypePrimitive::Bool); .)
+ | "false" (. e = Expression(Atom<Number_t>(0)); e.bindType(TypePrimitive::Bool); .)
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
- | '-' Factor< e> (. e = Expression(Operator::NEG, {e}); .)
+ | '-' Term<e> (. e = Expression(Operator::NEG, {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(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(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)); .).
+"ad" "hoc" MetaSimpExpr<command> (. AdhocExpression exprAdhoc; exprAdhoc.setCommand(command); e = exprAdhoc; .).
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; .)
( equal
| (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 f72b68e..9f1f85a 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,73 +1,69 @@
{
"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": "containers",
+ "template": "default",
"templates": {
"default": "*-",
- "basic": "Basic.*",
+ "adhocs": "Adhoc.*",
+ "effects": "Effects.*",
+ "basic": "Attachments.*",
"ast": "AST.*",
"cfa": "CFA.*",
"dfa": "DFA.*",
- "compilation": "Compilation.*",
- "containers": "Containers.ListAsArray2-",
+ "compilation": "Compilation.*",
"diagnostic": "Diagnostic.*",
- "serializer": "ExpressionSerializer.*",
+ "ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
- "context": "ExpressionSerializer.*:Context.*",
- "types": "Types.*-",
- "log": "Logging*",
- "clang": "ClangAPI.*",
- "skip": "SkipDetection*:Adhoc_Loop_SkipDetection.*",
- "raw-xml": "libxml2*",
- "xml": "Xml.*",
- "installation": "Compilation.*:Sprint1.*",
- "exploitation": "Exploitation.*",
- "loops": "Loop.*",
+ "types": "Types.*-",
+ "vendorsAPI/clang": "ClangAPI.*",
+ "vendorsAPI/xml2": "libxml2*",
"dsl": "Interpretation.*",
- "adhocs": "Adhoc.*",
+ "context": "Context.*",
+ "containers": "Containers.*",
+ "loops": "Loop.*"
}
}
}
diff --git a/core/containers.lp b/core/containers.lp
index 63b7269..16b5432 100644
--- a/core/containers.lp
+++ b/core/containers.lp
@@ -1,58 +1,44 @@
%defines
- impl(solid; on_the_fly; linked_list).
- op(seqaccess; randaccess).
+ impl(llvm_array; llvm_const_array; on_the_fly).
+ op(seqaccess). op(randaccess).
relation(recommends; satisfied; unsupported).
relation_score(satisfied, 0).
relation_score(recommends, 1).
relation_score(unsupported, -1).
score(-1..1).
%domain facts:
relation_op(seqaccess, on_the_fly, recommends).
-
- relation_op(randaccess, solid, recommends).
+ relation_op(randaccess, llvm_const_array, recommends).
relation_op(randaccess, on_the_fly, unsupported).
%dfa analysis:
-%scheme: dfa_connection(Vto, Vfrom, proto);
-%-- dfa_connection(VTo, VFrom, alias);
-%-- dfa_connection(VFormal, VActual, arg);
-%-- dfa_connection(VActual, VFormal, ret)
+% --
%compilation:
%--
%domain rules:
- %aliases:
- var_origin(VAR) :- not dfa_connection(VAR, _, alias), v(VAR).
- var_alias(VAR0, VAR_TO) :- dfa_connection(VAR_TO, VAR0, alias), var_origin(VAR0).
- var_alias(VAR0, VAR_TO2) :- dfa_connection(VAR_TO2, VAR_TO1, alias), var_alias(VAR0, VAR_TO1).
- var_alias(VAR0, VAR0):- var_origin(VAR0).
-
- %prototypes:
- var_proto(V0, Vproto) :- var_origin(V0); var_origin(Vproto); var_alias(Vproto, Vp); dfa_connection(V0, Vp, proto).
-
- %implementations:
-impl_fulfill(OP, IMPL) :- relation_op(OP, IMPL, unsupported).
impl_fulfill(OP, IMPL, SCORE):- SCORE = #sum{SCORE1, (OP, IMPL, RL): relation_op(OP, IMPL, RL),relation_score(RL, SCORE1)}
; op(OP); impl(IMPL); not -impl_fulfill(OP, IMPL).
- -var_impl_fulfill(Var0, Impl) :- var_alias(Var0, Var_Any); bind(Var_Any, op(Op)); -impl_fulfill(Op, Impl).
- var_impl_fulfill(VAR0, IMPL, Score) :-
- Score = #sum{SCORE, (OP, IMPL, VAR_ANY): impl_fulfill(OP, IMPL, SCORE), var_alias(VAR0, VAR_ANY), bind(VAR_ANY, op(OP))}
- ; bind(VAR0, impl(IMPL)); var_origin(VAR0); not -var_impl_fulfill(VAR0, IMPL).
+ cluster_root(VAR) :- not dfa_connection(VAR, _, strong), v(VAR).
+ var_cluster(VAR0, VAR_TO) :- dfa_connection(VAR_TO, VAR0, strong), cluster_root(VAR0).
+ var_cluster(VAR0, VAR_TO2) :- dfa_connection(VAR_TO2, VAR_TO1, strong), var_cluster(VAR0, VAR_TO1).
+ var_cluster(VAR0, VAR0):- cluster_root(VAR0).
- %transfunction implementation:
- %bind(Vactual, op(Op)) :- var_alias(Vformal, V1); bind(V1, op(Op)); dfa_connection(Vformal, Vactual, arg); op(Op).
+ -impl_fulfill_cluster(Var0, Impl) :- var_cluster(Var0, Var_Any); bind(Var_Any, op(Op)); -impl_fulfill(Op, Impl).
+ impl_fulfill_cluster(VAR0, IMPL, Score) :-
+ Score = #sum{SCORE, (OP, IMPL, VAR_ANY): impl_fulfill(OP, IMPL, SCORE), var_cluster(VAR0, VAR_ANY), bind(VAR_ANY, op(OP))}
+ ; bind(VAR0, impl(IMPL)); cluster_root(VAR0); not -impl_fulfill_cluster(VAR0, IMPL).
+
- %bind(Vactual, op(Op)) :- var_alias(VO, Vformal); var_alias(VO, V); bind(V, op(Op)); dfa_connection(Vactual,Vformal, ret); op(Op).
- % --uncomment to add possible implementations(impl) to an actual var
- %bind(Vres, op(Op)) :- var_alias(VO, VA); bind(VA, op(Op)); dfa_connection(VArg,VO, result); op(Op).
+ proto_cluster(V0, Vproto) :- cluster_root(V0); cluster_root(Vproto); var_cluster(Vproto, Vp); dfa_connection(V0, Vp, proto).
%optimization
-% #maximize {SCORE, (VAR0, IMPL) : var_impl_fulfill(VAR0, IMPL, SCORE)}.
+% #maximize {SCORE, (VAR0, IMPL) : impl_fulfill_cluster(VAR0, IMPL, SCORE)}.
-#show var_alias/2.
-#show var_impl_fulfill/3.
-#show proto_alias2.
+#show var_cluster/2.
+#show impl_fulfill_cluster/3.
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index beae275..0f5feae 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,34 +1,35 @@
+project(Xreate)
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
set(CMAKE_BUILD_TYPE Debug)
# 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 -fPIC -std=c++14)
# XREATE
#======================
add_subdirectory(src)
# XREATE-TESTS
#======================
if (BUILD_XREATE_TESTS)
message ("Building xreate tests")
add_subdirectory(tests)
endif ()
# XREATE-SERVER
#======================
if (BUILD_XREATE_SERVER)
message ("Building xreate server")
add_subdirectory(../tools/execution-server execution-server)
endif ()
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index f44d338..c42834a 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,211 +1,218 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
message("LLVM DEFS: " ${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option)
message("LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# 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_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
set(COCO_SOURCE_FILES
${COCO_GRAMMAR_PATH}/Parser.cpp
${COCO_GRAMMAR_PATH}/Scanner.cpp)
INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH})
add_custom_command(OUTPUT ${COCO_SOURCE_FILES}
COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH}
WORKING_DIRECTORY ${COCO_GRAMMAR_PATH}
MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG
)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
# XREATE
#======================
set(SOURCE_FILES
- pass/compilepass.cpp
- ast.cpp
- ExternLayer.cpp
- attachments.cpp
- analysis/cfagraph.cpp
- analysis/dfagraph.cpp
- analysis/aux.cpp
- compilation/containers.cpp
- compilation/advanced.cpp
compilation/transformations.cpp
- clasplayer.cpp
- compilation/latecontextcompiler2.cpp
- query/context.cpp
- #compilation/latecontextcompiler.cpp
- serialization/expressionserializer2.cpp
- llvmlayer.cpp
- utils.cpp
- passmanager.cpp
- pass/abstractpass.cpp pass/dfapass.cpp
- pass/cfapass.cpp
- pass/adhocpass.cpp
- contextrule.cpp
- query/containers.cpp
- pass/loggerpass.cpp
- pass/interpretationpass.cpp
- serialization/expressionserializer.cpp
+ compilation/transformersaturation.cpp
+ pass/compilepass.cpp
+ pass/dfapass.cpp
+ analysis/dfagraph.cpp
+
+ pass/versionspass.cpp
compilation/targetinterpretation.cpp
- analysis/DominatorsTreeAnalysisProvider.cpp
+
+ attachments.cpp
+ ast.cpp
- #query/ptrvalid.cpp
- #pass/rulespass.cpp #
+ ExternLayer.cpp
+
+ analysis/cfagraph.cpp
+
+ analysis/aux.cpp
+ compilation/containers.cpp
+ compilation/advanced.cpp
+
+ clasplayer.cpp
+ compilation/latecontextcompiler2.cpp
+ query/context.cpp
+
+ llvmlayer.cpp
+ utils.cpp
+ passmanager-bare.cpp
+ passmanager-full.cpp
+ pass/abstractpass.cpp
+
+ pass/cfapass.cpp
+ pass/adhocpass.cpp
+ contextrule.cpp
+ query/containers.cpp
+ pass/interpretationpass.cpp
+ analysis/DominatorsTreeAnalysisProvider.cpp
+ serialization/expressionserializer.cpp
)
set(XREATE_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/
)
INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS})
set(XREATE_PRIVATE_INCLUDE_DIRS
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_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})
target_include_directories(${PROJECT_NAME} INTERFACE
${XREATE_INCLUDE_DIRS}
${COCO_GRAMMAR_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 ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb
)
#${CLANG_LIBS}
#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/analysis/aux.cpp b/cpp/src/analysis/aux.cpp
index 6d5192c..7ac53fc 100644
--- a/cpp/src/analysis/aux.cpp
+++ b/cpp/src/analysis/aux.cpp
@@ -1,136 +1,136 @@
#include "aux.h"
#include <boost/format.hpp>
namespace xreate { namespace analysis {
using namespace std;
list<string>
multiplyLists(list<list<string>> &&lists) {
typedef list<string> StringList;
assert(lists.size());
StringList result(*lists.begin());
lists.pop_front();
boost::format concat("%s, %s");
for (StringList &list: lists) {
StringList::const_iterator end = result.end();
for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
if (list.size() == 0) continue;
StringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
result.push_back(str(concat %(*expr1I) %(*expr2I)));
*expr1I = str(concat %(*expr1I) %(*expr2I));
}
}
return result;
}
std::list<std::string>
compile(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
std::list<list<string>> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[](const Expression &e) {
return compile(e);
});
list<string> &&operands_ = multiplyLists(std::move(operands));
result.push_back(boost::str(boost::format("%1%(%2%)") % (e.getValueString()) % (boost::algorithm::join(operands_, ", "))));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::NONE: {
switch (e.__state) {
case Expression::IDENT:
result.push_back(e.getValueString());
break;
case Expression::NUMBER:
result.push_back(to_string(e.getValueDouble()));
break;
default:
assert(true);
}
break;
}
default: break;
}
//TODO Null ad hoc ClaspLayer implementation
// if (e.isNone()){
// result.push_back(e.__valueS);
// }
assert(result.size());
return result;
}
std::list<std::string>
compileNeg(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
list<string> operands1 = compile(e.operands.at(0));
list<string> operands2 = compile(e.operands.at(1));
boost::format formatNeg("%1%, not %2%");
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back(rawOp.front());
break;
};
default:
assert(true);
}
return result;
}
-boost::format
+boost::format
formatSymbol(const SymbolPacked& s){
- boost::format formatSymbNamed("(%1%, %2%)");
- boost::format formatSymbAnonymous("(anonym(%1%), %2%)");
+ boost::format formatSymbNamed("(%1%, %2%, %3%)");
+ boost::format formatSymbAnonymous("anonym(%1%, %2%)");
if (!s.categoryTransient){
- return formatSymbNamed % s.identifier % s.scope;
+ return formatSymbNamed % s.identifier % s.version % s.scope;
} else {
return formatSymbAnonymous % s.identifier % s.scope;
}
}
-
+
}}
\ No newline at end of file
diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp
index 00a3006..b1f52dc 100644
--- a/cpp/src/analysis/dfagraph.cpp
+++ b/cpp/src/analysis/dfagraph.cpp
@@ -1,250 +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;
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 << formatDfaConnection
% formatSymbol(i1->first)
% formatSymbol(i1->second)
% edgeName
<< " %" << this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second)
<< 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;
}
}
class VisitorAddTag : public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& symbol) {
__graph->__tags.emplace(symbol, move(__tag));
}
- void operator()(SymbolTransient& symbol) {
+ void operator()(SymbolAnonymous& symbol) {
symbol.tags.push_back(move(__tag));
}
void operator()(const SymbolInvalid& symbol) {
assert(false && "Undefined behaviour");
}
VisitorAddTag(DFAGraph * const dfagraph, Expression&& tag) :
__graph(dfagraph), __tag(tag) {
}
private:
DFAGraph * const __graph;
Expression __tag;
};
class VisitorAddLink : public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& nodeFrom) {
if (!__graph->isConnected(__nodeTo, nodeFrom)) {
__graph->__edges.emplace_back(__nodeTo, nodeFrom);
__graph->__data.push_back(__link);
DFAGraph::EdgeId eid = __graph->__edges.size() - 1;
__graph->__outEdges.emplace(nodeFrom, eid);
}
}
- void operator()(const SymbolTransient& symbolFrom) {
+ void operator()(const SymbolAnonymous& 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;
assert(false && "Undefined behavior");
}
VisitorAddLink(DFAGraph * const dfagraph, const SymbolPacked& nodeTo, DFGConnection link) :
__graph(dfagraph), __nodeTo(nodeTo), __link(link) {
}
private:
DFAGraph * const __graph;
SymbolPacked __nodeTo;
DFGConnection __link;
};
class VisitorGetDependencyConnection : public boost::static_visitor<list<SymbolPacked>>
{
public:
list<SymbolPacked>
operator()(const SymbolPacked & nodeFrom) {
return
{
nodeFrom
};
}
list<SymbolPacked>
- operator()(const SymbolTransient & nodeFrom) {
+ operator()(const SymbolAnonymous & 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);
}
}
- void operator()(SymbolTransient& nodeTo) {
+ void operator()(SymbolAnonymous& nodeTo) {
VisitorGetDependencyConnection visitorGetDepenencies(graph);
auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
for (const SymbolPacked& dep : deps) {
nodeTo.dependencies.push_back(dep);
}
}
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);
+ return SymbolPacked(ScopedSymbol{__countAnonymousSymbols++, 0}, scope, true);
}
}
}
\ No newline at end of file
diff --git a/cpp/src/analysis/dfagraph.h b/cpp/src/analysis/dfagraph.h
index 374ab14..7962c77 100644
--- a/cpp/src/analysis/dfagraph.h
+++ b/cpp/src/analysis/dfagraph.h
@@ -1,57 +1,60 @@
/*
* File: dfa.h
* Author: pgess
*
* Created on June 27, 2016, 1:50 PM
*/
#ifndef DFA_H
#define DFA_H
#include "clasplayer.h"
namespace xreate {namespace analysis {
- struct SymbolTransient {
+ struct SymbolAnonymous {
+ SymbolAnonymous(unsigned int symbolId): id(symbolId){}
+
+ unsigned int id;
std::list<Expression> tags;
ScopePacked scope;
std::list<SymbolPacked> dependencies;
};
-
+
struct SymbolInvalid { };
- typedef boost::variant<SymbolInvalid, SymbolTransient, xreate::SymbolPacked> SymbolNode;
+ typedef boost::variant<SymbolInvalid, SymbolAnonymous, SymbolPacked> SymbolNode;
class DFAGraph: public IAnalysisData{
friend class VisitorAddTag;
friend class VisitorAddLink;
friend class VisitorGetDependencyConnection;
friend class VisitorSetDependencyConnection;
public:
DFAGraph(ClaspLayer* engine): __clasp(engine){}
SymbolPacked createAnonymousSymbol(const ScopePacked& scope);
void addAnnotation(SymbolNode& identifier, Expression&& tag);
void addConnection(const SymbolPacked& identifierTo, const SymbolNode& identifierFrom, DFGConnection link);
void addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom);
bool isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom);
void print(std::ostringstream& output) const;
private:
typedef unsigned int EdgeId;
std::vector<std::pair<SymbolPacked, SymbolPacked>> __edges;
std::multimap<SymbolPacked, EdgeId> __outEdges;
std::vector<DFGConnection> __data;
std::multimap<SymbolPacked, Expression> __tags;
std::multimap<SymbolPacked, SymbolPacked> __dependencies;
unsigned int __countAnonymousSymbols=0;
ClaspLayer* __clasp;
};
}}
#endif /* DFA_H */
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 0ae05a9..95f4f66 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,816 +1,890 @@
#include "ast.h"
#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
-#include <clasplayer.h>
+
+namespace std{
+
+ std::size_t
+ hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const
+ {return s.id ^ (s.version << 2);}
+
+ bool
+ equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const
+ { return __x.id == __y.id && __x.version == __y.version; }
+}
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);
+namespace xreate {
- case Expression::IDENT:
- case Expression::STRING:
- return true;
+Atom<Identifier_t>::Atom(const std::wstring& value) {
+ __value = wstring_to_utf8(value);
+}
- case Expression::NUMBER:
- case Expression::BINDING:
- return false;
+Atom<Identifier_t>::Atom(std::string && name) : __value(name)
+{}
+
+const std::string&
+Atom<Identifier_t>::get() const {
+ return __value;
+}
- case Expression::COMPOUND: {
- switch (e.op){
- case Operator::CALL:
- case Operator::INDEX:
- return true;
+Atom<Number_t>::Atom(wchar_t* value) {
+ //DEBT reconsider number literal recognition
+ __value = wcstol(value, 0, 10);
+}
+
+Atom<Number_t>::Atom(int value)
+: __value(value) {
+}
- default: return false;
+double
+Atom<Number_t>::get()const {
+ return __value;
+}
+
+Atom<String_t>::Atom(const std::wstring& value) {
+ assert(value.size() >=2);
+ __value = wstring_to_utf8(value.substr(1, value.size() -2));
+}
+
+const std::string&
+Atom<String_t>::get() const {
+ return __value;
+}
+
+ class ExpressionHints {
+ public:
+
+ static bool
+ isStringValueValid(const Expression& e) {
+ switch (e.__state) {
+ case Expression::INVALID:
+ assert(false);
+
+ case Expression::IDENT:
+ case Expression::STRING:
+ return true;
+
+ case Expression::NUMBER:
+ case Expression::BINDING:
+ case Expression::VARIANT:
+ return false;
+
+ case Expression::COMPOUND:
+ {
+ switch (e.op) {
+ case Operator::CALL:
+ return true;
+
+ default: return false;
+ }
}
}
+
+ return false;
}
- return false;
- }
+ static bool
+ isDoubleValueValid(const Expression& e) {
+ switch (e.__state) {
+ case Expression::NUMBER:
+ case Expression::VARIANT:
+ return true;
+
+ case Expression::INVALID:
+ assert(false);
+
+ case Expression::IDENT:
+ case Expression::STRING:
+ case Expression::COMPOUND:
+ case Expression::BINDING:
+ return false;
+ }
- static bool
- isDoubleValueValid(const Expression& e){
- switch (e.__state){
- case Expression::NUMBER:
- return true;
+ return false;
+ }
+ };
- case Expression::INVALID:
- case Expression::VARIANT:
- assert(false);
+ class TypesResolver {
+ private:
+ const AST* ast;
+ std::map<std::string, TypeAnnotation> scope;
+ std::map<TypeAnnotation, int> signatures;
- case Expression::IDENT:
- case Expression::STRING:
- case Expression::COMPOUND:
- case Expression::BINDING:
- return false;
+ ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
+ return TypesResolver(ast, scope, signatures)(t, args);
}
- return false;
- }
-};
+ std::vector<TypeAnnotation>
+ expandOperands(const std::vector<TypeAnnotation>& operands) {
+ std::vector<TypeAnnotation> pack;
-class TypesResolver {
-private:
- const AST* ast;
- std::map<std::string, TypeAnnotation> scope;
- std::map<TypeAnnotation, int> signatures;
+ pack.reserve(operands.size());
+ std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
+ [this](const TypeAnnotation & t) {
+ return expandType(t);
+ });
+ return pack;
+ }
- ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()){
- return TypesResolver(ast, scope, signatures)(t, args);
- }
+ public:
- 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) {
- }
+ 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);
- 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, 0));
+ }
- Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
- return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
- }
+ case TypeOperator::STRUCT:
+ {
+ assert(t.__operands.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;
- std::vector<TypeAnnotation>&& pack = expandOperands(t.__operands);
- auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack));
- tnew.fields = t.fields;
+ return ExpandedType(move(tnew));
+ };
- return ExpandedType(move(tnew));
- };
+ case TypeOperator::CALL:
+ {
+ std::string alias = t.__valueCustom;
- case TypeOperator::CALL:
- {
- std::string alias = t.__valueCustom;
+ //find in local scope:
+ TypeAnnotation ty;
+ if (scope.count(alias)) {
+ ty = scope.at(alias);
- //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 if (ast->__indexTypeAliases.count(alias)){
- ty = ast->__indexTypeAliases.at(alias);
+ } else {
+ assert(false && "Undefined or external type");
+ }
- } else {
- assert(false && "Undefined or external type");
- }
+ std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
+ TypeAnnotation signature(TypeOperator::CALL, move(operands));
+ signature.__valueCustom = alias;
- 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);
- if (signatures.count(signature)) {
- auto link = TypeAnnotation(TypeOperator::LINK, {});
- link.conjuctionId = signatures.at(signature);
+ return ExpandedType(move(link));
+ }
- return ExpandedType(move(link));
- }
+ int cid = signatures.size();
+ signatures[signature] = cid;
+ TypeAnnotation tyResult = expandType(ty, operands);
+ tyResult.conjuctionId = cid;
- int cid = signatures.size();
- signatures[signature] = cid;
- TypeAnnotation tyResult = expandType(ty, operands);
- tyResult.conjuctionId = cid;
+ return ExpandedType(move(tyResult));
+ };
- return ExpandedType(move(tyResult));
- };
+ case TypeOperator::CUSTOM:
+ {
+ std::string alias = t.__valueCustom;
- 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());
+ /*
+ if (signatures.count(alias)) {
+ return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
+ }
+ signatures[alias].emplace(t);
+ */
- //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");
- }
+ //find in local scope:
+ if (scope.count(alias)) {
+ return expandType(scope.at(alias));
+ }
- 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");
+ // find in general scope:
+ if (ast->__indexTypeAliases.count(alias)) {
+ return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
+ }
- int fieldId = fieldIt - tyAlias->fields.begin();
- tyAlias = expandType(tyAlias->__operands.at(fieldId));
- }
+ //if type is unknown keep it as is.
+ return ExpandedType(TypeAnnotation(t));
+ };
- return tyAlias;
- }
+ case TypeOperator::ACCESS:
+ {
+ std::string alias = t.__valueCustom;
+ ExpandedType tyAlias = ExpandedType(TypeAnnotation());
- case TypeOperator::TUPLE: {
- assert(t.__operands.size());
+ //find in local scope:
+ if (scope.count(alias)) {
+ tyAlias = expandType(scope.at(alias));
- std::vector<TypeAnnotation> pack;
- pack.reserve(t.__operands.size());
+ //find in global scope:
+ } else if ((ast->__indexTypeAliases.count(alias))) {
+ tyAlias = expandType(ast->__indexTypeAliases.at(alias));
- std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()),
- [this](const TypeAnnotation& t){
- return expandType(t);
- });
+ } else {
+ assert(false && "Undefined or external type");
+ }
- return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
- }
-
- case TypeOperator::VARIANT: {
- return ExpandedType(TypeAnnotation(t));
- }
+ assert(tyAlias->__operator == TypeOperator::STRUCT);
- case TypeOperator::NONE: {
- return ExpandedType(TypeAnnotation(t));
- }
-
- default:
- assert(false);
- }
-
- assert(false);
- return ExpandedType(TypeAnnotation());
- }
-};
+ for (const string& field : t.fields) {
+ auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
+ assert(fieldIt != tyAlias->fields.end() && "unknown field");
-TypeAnnotation::TypeAnnotation()
-{
-}
+ int fieldId = fieldIt - tyAlias->fields.begin();
+ tyAlias = expandType(tyAlias->__operands.at(fieldId));
+ }
-TypeAnnotation::TypeAnnotation(const Atom<Type_t> &typ)
- : __value(typ.get())
-{
- ;
-}
+ return tyAlias;
+ }
-TypeAnnotation::TypeAnnotation (TypePrimitive typ)
- : __value(typ)
-{}
+ case TypeOperator::TUPLE:
+ {
+ assert(t.__operands.size());
-TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
- : __operator(op), __operands(operands)
-{
+ 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);
+ });
-TypeAnnotation::TypeAnnotation (TypeOperator op, std::vector<TypeAnnotation>&& operands)
- : __operator(op), __operands(operands)
-{}
+ return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
+ }
+ case TypeOperator::VARIANT:
+ {
+ return ExpandedType(TypeAnnotation(t));
+ }
-TypeAnnotation::TypeAnnotation (llvm_array_tag, TypeAnnotation typ, int size)
- :TypeAnnotation(TypeOperator::ARRAY, {typ})
-{
- __size=size;
-}
+ case TypeOperator::NONE:
+ {
+ return ExpandedType(TypeAnnotation(t));
+ }
-bool
-TypeAnnotation::operator< (const TypeAnnotation& t) const{
- if (__operator != t.__operator) return __operator < t.__operator;
+ default:
+ assert(false);
+ }
- if (__operator == TypeOperator::NONE)
- return __value < t.__value;
+ assert(false);
+ return ExpandedType(TypeAnnotation());
+ }
+ };
- if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS){
- if (__valueCustom != t.__valueCustom)
- return __valueCustom < t.__valueCustom;
- }
+ TypeAnnotation::TypeAnnotation()
+ : __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid)
+ {}
- return __operands < t.__operands;
-}
+ TypeAnnotation::TypeAnnotation(TypePrimitive typ)
+ : __value(typ) {
+ }
-/*
-TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
-{}
-*/
+ TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
+ : __operator(op), __operands(operands) {
-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(); });
-}
+ TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
+ : __operator(op), __operands(operands) {
+ }
-void
-TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields)
-{
- fields.reserve(fields.size() + listFields.size());
+ TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
+ : TypeAnnotation(TypeOperator::ARRAY,{typ}) {
+ __size = size;
+ }
- std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
- [](const Atom<Identifier_t>& ident){return ident.get(); });
-}
+ bool
+ TypeAnnotation::isValid() const{
+ return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
+ }
-Expression::Expression(const Atom<Number_t>& number)
-: __state(NUMBER), op(Operator::NONE), __valueD(number.get())
-{
-}
+ bool
+ TypeAnnotation::operator<(const TypeAnnotation& t) const {
+ if (__operator != t.__operator) return __operator < t.__operator;
-Expression::Expression(const Atom<String_t>& a)
- : __state(STRING), op(Operator::NONE), __valueS(a.get())
-{
-}
+ if (__operator == TypeOperator::NONE)
+ return __value < t.__value;
-Expression::Expression(const Atom<Identifier_t> &ident)
- : __state(IDENT), op(Operator::NONE), __valueS(ident.get())
-{
-}
+ if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
+ if (__valueCustom != t.__valueCustom)
+ return __valueCustom < t.__valueCustom;
+ }
+
+ return __operands < t.__operands;
+ }
-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();
+ /*
+ TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
+ {}
+ */
- assert(arg.__state == Expression::IDENT);
- __valueS = std::move(arg.__valueS);
+ void
+ TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
+ bindings.reserve(bindings.size() + params.size());
- operands.insert(operands.end(), params.begin()+1, params.end());
- return;
+ std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
+ [](const Atom<Identifier_t>& ident) {
+ return ident.get(); });
}
- operands.insert(operands.end(), params.begin(), params.end());
-}
+ void
+ TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
+ fields.reserve(fields.size() + listFields.size());
-void
-Expression::setOp(Operator oprt)
-{
- op = oprt;
+ std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
+ [](const Atom<Identifier_t>& ident) {
+ return ident.get(); });
+ }
- switch (op)
- {
- case Operator::NONE:
- __state = INVALID;
- break;
+ unsigned int Expression::nextVacantId = 0;
- default:
- __state = COMPOUND;
- break;
+ Expression::Expression(const Atom<Number_t>& number)
+ : Expression() {
+ __state=NUMBER; op=Operator::NONE; __valueD=number.get();
}
-}
-void
-Expression::addArg(Expression &&arg)
-{
- operands.push_back(arg);
-}
+ Expression::Expression(const Atom<String_t>& a)
+ : Expression(){
+ __state=STRING; op=Operator::NONE; __valueS=a.get();
+ }
-void
-Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params)
-{
- addBindings(params.begin(), params.end());
-}
+ Expression::Expression(const Atom<Identifier_t> &ident)
+ : Expression() {
+ __state=IDENT; op=Operator::NONE; __valueS=ident.get();
+ }
-void
-Expression::bindType(TypeAnnotation t)
-{
- type = move(t);
-}
+ Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
+ : Expression() {
+ __state=COMPOUND; op=oprt;
-void
-Expression::addBlock(ManagedScpPtr scope)
-{
- blocks.push_back(scope.operator ->());
-}
+ if (op == Operator::CALL) {
+ assert(params.size() > 0);
+ Expression arg = *params.begin();
-const std::vector<Expression>&
-Expression::getOperands() const
-{
- return operands;
-}
+ assert(arg.__state == Expression::IDENT);
+ __valueS = std::move(arg.__valueS);
-double
-Expression::getValueDouble() const
-{
- return __valueD;
-}
+ operands.insert(operands.end(), params.begin() + 1, params.end());
+ return;
+ }
-const std::string&
-Expression::getValueString() const
-{
- return __valueS;
-}
+ operands.insert(operands.end(), params.begin(), params.end());
+ }
-void
-Expression::setValue(const Atom<Identifier_t>&& v){
- __valueS = v.get();
-}
+ void
+ Expression::setOp(Operator oprt) {
+ op = oprt;
-void Expression::setValueDouble(double value){
- __valueD = value;
-}
+ switch (op) {
+ case Operator::NONE:
+ __state = INVALID;
+ break;
-bool
-Expression::isValid() const{
- return (__state != INVALID);
-}
+ default:
+ __state = COMPOUND;
+ break;
+ }
+ }
-bool
-Expression::isDefined() const{
- return (__state != BINDING);
-}
+ void
+ Expression::addArg(Expression &&arg) {
+ operands.push_back(arg);
+ }
-Expression::Expression()
- : __state(INVALID), op(Operator::NONE)
-{}
+ void
+ Expression::addTags(const std::list<Expression> tags) const{
+ std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
+ [](const Expression& tag){
+ return make_pair(tag.getValueString(), tag);
+ });
+ }
-bool
-Expression::operator==(const Expression& other) const{
- assert(!this->blocks.size());
- assert(!other.blocks.size());
+ void
+ Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
+ addBindings(params.begin(), params.end());
+ }
- if (this->__state != other.__state) return false;
+ void
+ Expression::bindType(TypeAnnotation t) {
+ type = move(t);
+ }
- if (ExpressionHints::isStringValueValid(*this)){
- if (this->__valueS != other.__valueS) return false;
+ void
+ Expression::addBlock(ManagedScpPtr scope) {
+ blocks.push_back(scope.operator->());
}
- if (ExpressionHints::isDoubleValueValid(*this)){
- if (this->__valueD != other.__valueD) return false;
+ const std::vector<Expression>&
+ Expression::getOperands() const {
+ return operands;
}
- if (this->__state != Expression::COMPOUND){
- return true;
+ double
+ Expression::getValueDouble() const {
+ return __valueD;
}
- if (this->operands.size() != other.operands.size()){
- return false;
+ const std::string&
+ Expression::getValueString() const {
+ return __valueS;
}
- for (size_t i=0; i<this->operands.size(); ++i){
- if (!(this->operands[i]==other.operands[i])) return false;
+ void
+ Expression::setValue(const Atom<Identifier_t>&& v) {
+ __valueS = v.get();
}
- return true;
-}
+ void Expression::setValueDouble(double value) {
+ __valueD = value;
+ }
+ bool
+ Expression::isValid() const {
+ return (__state != INVALID);
+ }
-AST::AST()
-{
-}
+ bool
+ Expression::isDefined() const {
+ return (__state != BINDING);
+ }
+ Expression::Expression()
+ : __state(INVALID), op(Operator::NONE), id(nextVacantId++)
+ { }
-void
-AST::addInterfaceData(const ASTInterface& interface, Expression&& data ) {
- __interfacesData.emplace(interface, move(data));
-}
+ bool
+ Expression::operator==(const Expression& other) const {
+ if (this->__state != other.__state) return false;
-void
-AST::addDFAData(Expression &&data) {
- __dfadata.push_back(data);
-}
+ if (ExpressionHints::isStringValueValid(*this)) {
+ if (this->__valueS != other.__valueS) return false;
+ }
-void
-AST::addExternData(ExternData &&data) {
- __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
-}
+ if (ExpressionHints::isDoubleValueValid(*this)) {
+ if (this->__valueD != other.__valueD) return false;
+ }
-void
-AST::add(Function* f)
-{
- __functions.push_back(f);
- __indexFunctions.emplace(f->getName(), __functions.size()-1);
-}
+ if (this->__state != Expression::COMPOUND) {
+ return true;
+ }
-void
-AST::add(MetaRuleAbstract *r)
-{
- __rules.push_back(r);
-}
+ if (this->op != other.op) {
+ return false;
+ }
-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));
- }
- }
+ if (this->operands.size() != other.operands.size()) {
+ return false;
+ }
- __indexTypeAliases.emplace(alias.get(), move(t));
-}
+ for (size_t i = 0; i<this->operands.size(); ++i) {
+ if (!(this->operands[i] == other.operands[i])) return false;
+ }
-ManagedScpPtr
-AST::add(CodeScope* scope)
-{
- this->__scopes.push_back(scope);
- return ManagedScpPtr(this->__scopes.size()-1, &this->__scopes);
-}
+ assert(!this->blocks.size());
+ assert(!other.blocks.size());
-std::string
-AST::getModuleName()
-{
- const std::string name = "moduleTest";
+ return true;
+ }
- return name;
-}
+ AST::AST() {
+ Attachments::init<VariableVersion>();
+ Attachments::init<Symbol>();
+ }
-ManagedPtr<Function>
-AST::findFunction(const std::string& name)
-{
- int count = __indexFunctions.count(name);
- if (!count) {
- return ManagedFnPtr::Invalid();
+ void
+ AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
+ __interfacesData.emplace(interface, move(data));
}
- assert(count ==1);
+ void
+ AST::addDFAData(Expression &&data) {
+ __dfadata.push_back(data);
+ }
- auto range = __indexFunctions.equal_range(name);
- return ManagedPtr<Function>(range.first->second, &this->__functions);
-}
+ void
+ AST::addExternData(ExternData &&data) {
+ __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
+ }
-std::list<ManagedFnPtr>
-AST::getAllFunctions() const{
- const size_t size = __functions.size();
+ void
+ AST::add(Function* f) {
+ __functions.push_back(f);
+ __indexFunctions.emplace(f->getName(), __functions.size() - 1);
+ }
- std::list<ManagedFnPtr> result;
- for (size_t i=0; i<size; ++i){
- result.push_back(ManagedFnPtr(i, &this->__functions));
- }
+ void
+ AST::add(MetaRuleAbstract *r) {
+ __rules.push_back(r);
+ }
- return result;
-}
+ 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));
+ }
+ }
-//TASK select default specializations
-std::list<ManagedFnPtr>
-AST::getFunctionVariants(const std::string& name) const{
- auto functions = __indexFunctions.equal_range(name);
+ __indexTypeAliases.emplace(alias.get(), move(t));
+ }
- std::list<ManagedFnPtr> result;
- std::transform(functions.first, functions.second, inserter(result, result.end()),
- [this](auto f){return ManagedFnPtr(f.second, &this->__functions);});
+ ManagedScpPtr
+ AST::add(CodeScope* scope) {
+ this->__scopes.push_back(scope);
+ return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
+ }
- return result;
-}
+ std::string
+ AST::getModuleName() {
+ const std::string name = "moduleTest";
- template<>
-ManagedPtr<Function>
-AST::begin<Function>()
-{return ManagedPtr<Function>(0, &this->__functions);}
+ return name;
+ }
-template<>
-ManagedPtr<CodeScope>
-AST::begin<CodeScope>()
-{return ManagedPtr<CodeScope>(0, &this->__scopes);}
+ ManagedPtr<Function>
+ AST::findFunction(const std::string& name) {
+ int count = __indexFunctions.count(name);
+ if (!count) {
+ return ManagedFnPtr::Invalid();
+ }
-template<>
-ManagedPtr<MetaRuleAbstract>
-AST::begin<MetaRuleAbstract>()
-{return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);}
+ assert(count == 1);
+ auto range = __indexFunctions.equal_range(name);
+ return ManagedPtr<Function>(range.first->second, &this->__functions);
+ }
-Expanded<TypeAnnotation>
-AST::expandType(const TypeAnnotation &t) const
-{
- return TypesResolver(this)(t);
-}
+ std::list<ManagedFnPtr>
+ AST::getAllFunctions() const {
+ const size_t size = __functions.size();
-Expanded<TypeAnnotation>
-AST::findType(const std::string& name){
- // find in general scope:
- if(__indexTypeAliases.count(name))
- return expandType(__indexTypeAliases.at(name));
+ std::list<ManagedFnPtr> result;
+ for (size_t i = 0; i < size; ++i) {
+ result.push_back(ManagedFnPtr(i, &this->__functions));
+ }
- //if type is unknown keep it as is.
- TypeAnnotation t(TypeOperator::CUSTOM, {});
- t.__valueCustom = name;
- return ExpandedType(move(t));
-}
+ return result;
+ }
-void
-AST::recognizeVariantIdentifier(Expression& identifier){
+ //TASK select default specializations
-// 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
+ std::list<ManagedFnPtr>
+ AST::getFunctionVariants(const std::string& name) const {
+ auto functions = __indexFunctions.equal_range(name);
- assert(identifier.__state == Expression::IDENT);
+ std::list<ManagedFnPtr> result;
+ std::transform(functions.first, functions.second, inserter(result, result.end()),
+ [this](auto f) {
+ return ManagedFnPtr(f.second, &this->__functions);
+ });
- std::string name = identifier.getValueString();
- if (__dictVariants.count(name)){
- auto record = __dictVariants.at(name);
- const TypeAnnotation& typ = record.first;
+ return result;
+ }
- identifier.__state = Expression::VARIANT;
- identifier.setValueDouble(record.second);
- identifier.type = typ;
- }
-}
+ template<>
+ ManagedPtr<Function>
+ AST::begin<Function>() {
+ return ManagedPtr<Function>(0, &this->__functions);
+ }
-Function::Function(const Atom<Identifier_t>& name)
- : __entry(new CodeScope(0))
-{
- __name = name.get();
-}
+ template<>
+ ManagedPtr<CodeScope>
+ AST::begin<CodeScope>() {
+ return ManagedPtr<CodeScope>(0, &this->__scopes);
+ }
-void
-Function::addTag(Expression&& tag, const TagModifier mod)
-{
- string name = tag.getValueString();
- __tags.emplace(move(name), move(tag));
-}
+ template<>
+ ManagedPtr<MetaRuleAbstract>
+ AST::begin<MetaRuleAbstract>() {
+ return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
+ }
-const std::map<std::string, Expression>&
-Function::getTags() const
-{
- return __tags;
-}
+ Expanded<TypeAnnotation>
+ AST::expandType(const TypeAnnotation &t) const {
+ return TypesResolver(this)(t);
+ }
-CodeScope*
-Function::getEntryScope() const
-{
- return __entry;
-}
+ Expanded<TypeAnnotation>
+ AST::findType(const std::string& name) {
+ // find in general scope:
+ if (__indexTypeAliases.count(name))
+ return expandType(__indexTypeAliases.at(name));
-void
-Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument)
-{
- __entry->addBinding(move(name), move(argument));
-}
+ //if type is unknown keep it as is.
+ TypeAnnotation t(TypeOperator::CUSTOM,{});
+ t.__valueCustom = name;
+ return ExpandedType(move(t));
+ }
-void
-Function::setReturnType(const TypeAnnotation &rtyp)
-{
+ bool
+ AST::recognizeVariantIdentifier(Expression& identifier) {
+ assert(identifier.__state == Expression::IDENT);
- __entry->__declarations[0].type = rtyp;
-}
+ std::string variant = identifier.getValueString();
+ if (!__dictVariants.count(variant)) {
+ return false;
+ }
-const std::string&
-Function::getName() const
-{
- return __name;
-}
+ auto record = __dictVariants.at(variant);
+ const TypeAnnotation& typ = record.first;
-Symbol
-CodeScope::registerIdentifier(Atom <Identifier_t> &&name)
-{
- __identifiers.emplace(name.get(), ++__vCounter);
- return {__vCounter, this};
-}
+ identifier.__state = Expression::VARIANT;
+ identifier.setValueDouble(record.second);
+ identifier.type = typ;
-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);
-}
+ return true;
+ }
-void
-CodeScope::addDeclaration(Atom <Identifier_t>&& name, Expression&& body)
-{
- Symbol s = registerIdentifier(move(name));
- __declarations[s.identifier] = move(body);
-}
+ Function::Function(const Atom<Identifier_t>& name)
+ : __entry(new CodeScope(0)) {
+ __name = name.get();
+ }
-CodeScope::CodeScope(CodeScope* parent)
- :__parent(parent)
-{}
+ void
+ Function::addTag(Expression&& tag, const TagModifier mod) {
+ string name = tag.getValueString();
+ __tags.emplace(move(name), move(tag));
+ }
-CodeScope::~CodeScope()
-{}
+ const std::map<std::string, Expression>&
+ Function::getTags() const {
+ return __tags;
+ }
-void
-CodeScope::setBody(const Expression &body)
-{
- __declarations[0] = body;
-}
+ CodeScope*
+ Function::getEntryScope() const {
+ return __entry;
+ }
-Expression&
-CodeScope::getBody(){
- return __declarations[0];
-}
+ void
+ Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument) {
+ __entry->addBinding(move(name), move(argument));
+ }
-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;
+ const std::string&
+ Function::getName() const {
+ return __name;
+ }
+
+ ScopedSymbol
+ CodeScope::registerIdentifier(const Expression& identifier) {
+ VariableVersion version = Attachments::get<VariableVersion>(identifier, VERSION_NONE);
+
+ auto result = __identifiers.emplace(identifier.getValueString(), __vCounter);
+ if (result.second){
+ ++__vCounter;
+ return {__vCounter-1, version};
+ }
+
+ return {result.first->second, version};
}
+ bool
+ CodeScope::recognizeIdentifier(const Expression& identifier) const{
+ VariableVersion version = Attachments::get<VariableVersion>(identifier, VERSION_NONE);
+ const std::string& name = identifier.getValueString();
+
+ //search identifier in the current block
+ if (__identifiers.count(name)){
+ VNameId id = __identifiers.at(name);
+
+ Symbol s;
+ s.identifier = ScopedSymbol{id, version};
+ s.scope = const_cast<CodeScope*>(this);
+ Attachments::put<Symbol>(identifier, s);
+
+ return true;
+ }
+
//search in the parent scope
- if (__parent)
- {
- return __parent->findSymbol(name);
+ if (__parent)
+ {
+ return __parent->recognizeIdentifier(identifier);
+ }
+
+ return false;
}
- //exception: Ident not found
- std::cout << "Unknown symbol: "<< name << std::endl;
- assert(false && "Symbol not found");
-}
+ ScopedSymbol
+ CodeScope::getSymbol(const std::string& alias){
+ assert(__identifiers.count(alias));
+ VNameId id = __identifiers.at(alias);
-const Expression&
-CodeScope::findDeclaration(const Symbol& symbol)
-{
- CodeScope* self = symbol.scope;
- return self->__declarations[symbol.identifier];
-}
+ return {id, VERSION_NONE};
+ }
+ void
+ AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
+ binUnrecognizedIdentifiers.emplace(scope, id);
+ }
+ void
+ AST::recognizePostponedIdentifiers() {
+ for(const auto& identifier: binUnrecognizedIdentifiers){
+ if (!identifier.first->recognizeIdentifier(identifier.second)){
+ //exception: Ident not found
+ std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl;
+ assert(false && "Symbol not found");
+ }
+ }
+ }
-void
-RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ)
-{
- emplace_back(arg.get(), typ);
-}
+ void
+ CodeScope::addBinding(Expression&& var, Expression&& argument) {
+ argument.__state = Expression::BINDING;
-void
-RuleGuards::add(Expression&& e)
-{
- push_back(e);
-}
+ __bindings.push_back(var.getValueString());
+ ScopedSymbol binding = registerIdentifier(var);
+ __declarations[binding] = move(argument);
+ }
-MetaRuleAbstract::
-MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
- : __args(std::move(args)), __guards(std::move(guards))
-{}
+ void
+ CodeScope::addDeclaration(Expression&& var, Expression&& body) {
+ ScopedSymbol s = registerIdentifier(var);
+ __declarations[s] = move(body);
+ }
-MetaRuleAbstract::~MetaRuleAbstract(){}
+ CodeScope::CodeScope(CodeScope* parent)
+ : __parent(parent) {
+ }
-RuleWarning::
-RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
- : MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition)
-{}
+ CodeScope::~CodeScope() {
+ }
-RuleWarning::~RuleWarning(){}
+ void
+ CodeScope::setBody(const Expression &body) {
+ __declarations[ScopedSymbol::RetSymbol] = body;
+ }
-void
-RuleWarning::compile(ClaspLayer& layer)
-{
- //TODO restore addRuleWarning
- //layer.addRuleWarning(*this);
-}
+ Expression&
+ CodeScope::getBody() {
+ return __declarations[ScopedSymbol::RetSymbol];
+ }
-bool operator< (const Symbol& s1, const Symbol& s2)
-{
- return (s1.scope < s2.scope) || (s1.scope==s2.scope && s1.identifier<s2.identifier);
-}
+ const Expression&
+ CodeScope::getDeclaration(const Symbol& symbol) {
+ CodeScope* self = symbol.scope;
+ return self->getDeclaration(symbol.identifier);
+ }
-bool operator== (const Symbol& s1, const Symbol& s2)
-{
- return (s1.scope == s2.scope) && (s1.identifier==s2.identifier);
-}
+ const Expression&
+ CodeScope::getDeclaration(const ScopedSymbol& symbol){
+ assert(__declarations.count(symbol) && "Symbol's declaration not found");
-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());
- }
+ return __declarations.at(symbol);
+ }
- if (a.getValueString() != b.getValueString()){
- return a.getValueString() < b.getValueString();
- }
+ void
+ RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
+ emplace_back(arg.get(), typ);
+ }
- for(size_t i=0; i<a.operands.size(); ++i){
- bool result = a.operands[i] < b.operands[i];
- if (result) return true;
+ 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 ScopedSymbol& s1, const ScopedSymbol& s2) {
+ return (s1.id < s2.id) || (s1.id==s2.id && s1.version < s2.version);
+ }
+
+ bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
+ return (s1.id == s2.id) && (s1.version == s2.version);
+ }
+
+ 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;
}
- case Expression::BINDING:
- case Expression::INVALID:
- assert(false);
+const ScopedSymbol
+ScopedSymbol::RetSymbol = ScopedSymbol{0, VERSION_NONE};
}
-return false;
-}
-}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index cd070ab..7407463 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,562 +1,558 @@
#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);
- }
+struct String_t {
+};
- Atom(int value)
- : __value(value) {
- }
+struct Identifier_t {
+};
- double get()const {
- return __value;
- }
- private:
- double __value;
- };
+struct Number_t {
+};
- template<> class Atom<String_t> {
- public:
+struct Type_t {
+};
- Atom(const std::wstring& value) {
- assert(value.size());
- __value = std::string(++value.begin(), --value.end());
- }
+template<typename A>
+class Atom {
+};
- 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;
- }
- }
+//DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
+template<> class
+Atom<Identifier_t> {
+public:
+ Atom(const std::wstring& value);
+ Atom(std::string && name);
+ const std::string& get() const;
+
+private:
+ std::string __value;
+};
+
+template<>
+class Atom<Number_t> {
+public:
+ Atom(wchar_t* value);
+ Atom(int value);
+ double get()const;
+
+private:
+ double __value;
+};
- Atom() {
- }
+template<>
+class Atom<String_t> {
+public:
+ Atom(const std::wstring& value);
+ const std::string& get() const;
- TypePrimitive get() const {
- return __value;
- }
+private:
+ std::string __value;
+};
- private:
- TypePrimitive __value;
- };
-
- typedef Atom<Type_t> TypeAtom;
+enum class TypePrimitive {
+ Invalid, Bool, I8, I32, Num, Int, Float, String
+};
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>);
+ bool isValid() const;
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
+ ADD, SUB, MUL, DIV,
+ EQU, NE, NEG, LSS,
+ LSE, GTR, GTE, LIST,
+ LIST_RANGE, LIST_NAMED,
+ CALL, CALL_INTRINSIC, NONE,
+ IMPL/* implication */, MAP,
+ FOLD, FOLD_INF, LOOP_CONTEXT,
+ INDEX, IF, SWITCH, SWITCH_ADHOC,
+ CASE, CASE_DEFAULT, LOGIC_AND,
+ ADHOC, CONTEXT_RULE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
template<class Target>
struct ManagedPtr {
static ManagedPtr<Target> Invalid() {
return ManagedPtr<Target>();
}
ManagedPtr() : __storage(0) {
}
ManagedPtr(unsigned int id, const std::vector<Target*>* storage)
: __id(id), __storage(storage) {
}
Target&
operator*() const {
assert(isValid() && "Invalid Ptr");
return *__storage->at(__id);
}
void operator=(const ManagedPtr<Target>& other) {
__id = other.__id;
__storage = other.__storage;
}
bool
operator==(const ManagedPtr<Target>& other) {
return isValid() && (__id == other.__id);
}
Target*
operator->() const noexcept {
assert(isValid() && "Invalid Ptr");
return __storage->at(__id);
}
inline bool isValid() const {
return (__storage) && (0 <= __id) && (__id < __storage->size());
}
inline operator bool() const {
return isValid();
}
ManagedPtr<Target>& operator++() {
++__id;
return *this;
}
inline unsigned int id() 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 addTags(const std::list<Expression> tags) const;
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;
+ unsigned int id;
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;
+
+ static unsigned int nextVacantId;
};
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
+ typedef unsigned int VNameId;
+
+ typedef int VariableVersion;
+ const VariableVersion VERSION_NONE = -2;
+ const VariableVersion VERSION_INIT = 0;
+
+ template<>
+ struct AttachmentsDict<VariableVersion>
{
- friend class CFGPass;
-
- public:
- llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
+ typedef VariableVersion Data;
+ static const unsigned int key = 6;
+ };
+
+ struct ScopedSymbol{
+ VNameId id;
+ VariableVersion version;
+
+ static const ScopedSymbol RetSymbol;
+ };
+
+ struct Symbol {
+ ScopedSymbol identifier;
+ CodeScope * scope;
+ };
+
+ template<>
+ struct AttachmentsDict<Symbol>
+ {
+ typedef Symbol Data;
+ static const unsigned int key = 7;
+ };
+
+}
+namespace std
+{
+ template<>
+ struct hash<xreate::ScopedSymbol>{
+ std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
- */
+ template<>
+ struct equal_to<xreate::ScopedSymbol>{
+ bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
+ };
+}
+namespace xreate {
+
typedef std::pair<Expression, TagModifier> Tag;
- struct Symbol {
- VID identifier;
- CodeScope * scope;
- };
-
+ bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
+ bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
- class CodeScope {
- friend class Function;
- friend class PassManager;
+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;
- 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);
- };
+public:
+ CodeScope(CodeScope* parent = 0);
+ void setBody(const Expression& body);
+ Expression& getBody();
+ void addDeclaration(Expression&& var, Expression&& body);
+ void addBinding(Expression&& var, Expression&& argument);
+ static const Expression& getDeclaration(const Symbol& symbol);
+ const Expression& getDeclaration(const ScopedSymbol& symbol);
- class Function {
- friend class Expression;
- friend class CodeScope;
- friend class AST;
+ ~CodeScope();
- public:
- Function(const Atom<Identifier_t>& name);
+ std::vector<std::string> __bindings;
+ std::map<std::string, VNameId> __identifiers;
- void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
- void addTag(Expression&& tag, const TagModifier mod);
+ //TODO move __definitions to SymbolsAttachments data
+ //NOTE: definition of return type has zero(0) variable index
+ std::unordered_map<ScopedSymbol, Expression> __declarations;
+ std::vector<Expression> tags;
+ std::vector<Expression> contextRules;
- void setReturnType(const TypeAnnotation& rtyp);
+private:
+ VNameId __vCounter = 1;
+ CodeScope* __parent;
- 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
+ ScopedSymbol registerIdentifier(const Expression& identifier);
- Expression guardContext;
- private:
+public:
+ bool recognizeIdentifier(const Expression& identifier) const;
+ ScopedSymbol getSymbol(const std::string& alias);
+};
- std::map<std::string, Expression> __tags;
- };
+class Function {
+ friend class Expression;
+ friend class CodeScope;
+ friend class AST;
+public:
+ Function(const Atom<Identifier_t>& name);
- class ExternData;
+ void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
+ void addTag(Expression&& tag, const TagModifier mod);
- struct ExternEntry {
- std::string package;
- std::vector<std::string> headers;
- };
+ 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
- typedef Expanded<TypeAnnotation> ExpandedType;
+ Expression guardContext;
+private:
- enum ASTInterface {
- CFA, DFA, Extern, Adhoc
- };
+ std::map<std::string, Expression> __tags;
+};
- struct FunctionSpecialization {
- std::string guard;
- size_t id;
- };
- struct FunctionSpecializationQuery {
- std::unordered_set<std::string> context;
- };
+class ExternData;
- template<>
- struct AttachmentsStorage<Symbol> {
+struct ExternEntry {
+ std::string package;
+ std::vector<std::string> headers;
+};
- static Attachments*
- get(const Symbol& s) {
- return &s.scope->findDeclaration(s).tagsInternal;
- }
- };
+typedef Expanded<TypeAnnotation> ExpandedType;
- template<>
- struct AttachmentsStorage<Expression> {
+enum ASTInterface {
+ CFA, DFA, Extern, Adhoc
+};
- static Attachments*
- get(const Expression& e) {
- return &e.tagsInternal;
- }
- };
+struct FunctionSpecialization {
+ std::string guard;
+ size_t id;
+};
- class AST {
- public:
- AST();
+struct FunctionSpecializationQuery {
+ std::unordered_set<std::string> context;
+};
- //TASK extern and DFA interfaces move into addInterfaceData
- /**
- * DFA Interface
- */
- void addDFAData(Expression&& data);
+template<>
+struct AttachmentsId<Expression>{
+ static unsigned int getId(const Expression& expression){
+ return expression.id;
+ }
+};
- /**
- * Extern Interface
- */
- void addExternData(ExternData&& data);
+template<>
+struct AttachmentsId<Symbol>{
+ static unsigned int getId(const Symbol& s){
+ return s.scope->__declarations.at(s.identifier).id;
+ }
+};
- void addInterfaceData(const ASTInterface& interface, Expression&& data);
- void add(Function* f);
+template<>
+struct AttachmentsId<ManagedFnPtr>{
+ static unsigned int getId(const ManagedFnPtr& f){
+ const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
+
+ return AttachmentsId<Symbol>::getId(symbolFunction);
+ }
+};
- void add(MetaRuleAbstract* r);
- ManagedScpPtr add(CodeScope* scope);
+class AST {
+public:
+ AST();
- std::string getModuleName();
- ManagedPtr<Function> findFunction(const std::string& name);
+ //TASK extern and DFA interfaces move into addInterfaceData
+ /**
+ * DFA Interface
+ */
+ void addDFAData(Expression&& data);
- typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
- std::list<ManagedFnPtr> getAllFunctions() const;
- std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
+ /**
+ * Extern Interface
+ */
+ void addExternData(ExternData&& data);
+ void addInterfaceData(const ASTInterface& interface, Expression&& data);
+ void add(Function* f);
- template<class Target>
- ManagedPtr<Target> begin();
+ void add(MetaRuleAbstract* r);
+ ManagedScpPtr add(CodeScope* scope);
- 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.
+ std::string getModuleName();
+ ManagedPtr<Function> findFunction(const std::string& name);
- private:
- std::vector<MetaRuleAbstract*> __rules;
- std::vector<Function*> __functions;
- std::vector<CodeScope*> __scopes;
+ typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
+ std::list<ManagedFnPtr> getAllFunctions() const;
+ std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
- FUNCTIONS_REGISTRY __indexFunctions;
+ template<class Target>
+ ManagedPtr<Target> begin();
- // ***** 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);
+ 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;
- 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;
+ FUNCTIONS_REGISTRY __indexFunctions;
- // ***** TYPES SECTION END *****
- };
- template<>
- ManagedPtr<Function>
- AST::begin<Function>();
+ // ***** 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);
- template<>
- ManagedPtr<CodeScope>
- AST::begin<CodeScope>();
+ //TODO revisit enums/variants, move to codescope
+ bool recognizeVariantIdentifier(Expression& identifier);
- template<>
- ManagedPtr<MetaRuleAbstract>
- AST::begin<MetaRuleAbstract>();
+
+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;
+
+ // ***** SYMBOL RECOGNITION *****
+public:
+ std::set<std::pair<CodeScope*, Expression>> binUnrecognizedIdentifiers;
+
+public:
+ void postponeIdentifier(CodeScope* scope, const Expression& id);
+ void recognizePostponedIdentifiers();
+};
+
+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.cpp b/cpp/src/attachments.cpp
index 83a54d1..61fcdcd 100644
--- a/cpp/src/attachments.cpp
+++ b/cpp/src/attachments.cpp
@@ -1,30 +1,10 @@
//
// Created by pgess on 3/15/15.
//
#include "attachments.h"
-namespace xreate {
- void* xreate::Attachments::put(unsigned int key, void *data) {
- auto result = __data.emplace(key, data);
-
- void* ptrOld = nullptr;
- if (!result.second){
- ptrOld = result.first->second;
- result.first->second = data;
- }
-
- return ptrOld;
- }
+using namespace xreate;
- void *xreate::Attachments::get(unsigned int key) {
- assert(__data.count(key));
- return __data.at(key);
- }
-
- bool
- xreate::Attachments::exists(unsigned int key)
- {
- return __data.count(key)>0;
- }
-}
\ No newline at end of file
+std::vector<void*>
+Attachments::__storage = std::vector<void*>();
\ No newline at end of file
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index 03b8711..1fd3e48 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,124 +1,158 @@
//
// Created by pgess on 3/15/15.
//
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
-#include <map>
+#include <unordered_map>
+#include <vector>
#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 - 6);
+ // static const unsigned int key (current unreserved - 9);
};
- template<class T>
- struct AttachmentsStorage
- {
- //static Attachments* get(const T&);
+ template<class Object>
+ struct AttachmentsId{
+ //static unsigned int getId(const Object& object);
};
- namespace detail {
+
+template<class Data>
+class IAttachmentsContainer{
+ protected:
+ virtual bool __exists(const unsigned int object)=0;
+ virtual Data& __get(const unsigned int object)=0;
+ virtual void __put(const unsigned int object, Data data)=0;
- 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;
+ public:
+ template<class Id>
+ bool exists(const Id& object){
+ unsigned int id = AttachmentsId<Id>::getId(object);
+
+ return __exists(id);
}
-
- template<class Typ>
- typename std::enable_if<! std::is_pointer<Typ>::value, Typ&>::type
- __unwrap(void* value){
- return *reinterpret_cast<Typ*>(value);
+
+ template<class Id>
+ Data& get(const Id& object){
+ unsigned int id = AttachmentsId<Id>::getId(object);
+
+ return __get(id);
}
- template<class Typ>
- typename std::enable_if<std::is_pointer<Typ>::value, void>::type
- __delete(void* value){
- delete reinterpret_cast<Typ>(value);
+ template<class Id>
+ Data get(const Id& object, const Data& dataDefault){
+ unsigned int id = AttachmentsId<Id>::getId(object);
+
+ if (! __exists(id)){
+ return dataDefault;
+ }
+
+ return __get(id);
}
-
- template<class Typ>
- typename std::enable_if<! std::is_pointer<Typ>::value, void>::type
- __delete(void* value){
- delete reinterpret_cast<Typ*>(value);
+
+ template<class Id>
+ void put(const Id& object, Data data){
+ unsigned int id = AttachmentsId<Id>::getId(object);
+
+ __put(id, data);
}
- }
+
+ virtual ~IAttachmentsContainer(){};
+};
- //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 Data>
+class AttachmentsContainerDefault: public IAttachmentsContainer<Data>{
+private:
+ std::unordered_map<unsigned int, Data> __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);
+ virtual bool __exists(const unsigned int id){
+ return __data.count(id);
+ }
- void* dataWaste = self->put(key, detail::__wrap(data));
- detail::__delete<Data<Tag>>(dataWaste);
- }
+ virtual Data& __get(const unsigned int id){
+ return __data.at(id);
+ }
+
+ virtual void __put(const unsigned int id, Data data){
+ auto result = __data.emplace(id, data);
+ assert(result.second);
+ }
+};
- 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));
+class Attachments{
+ private:
+ static std::vector<void*> __storage;
+
+ template<class Tag>
+ using Data = typename AttachmentsDict<Tag>::Data;
+
+ public:
+ template<class Tag, class Id>
+ static bool exists(const Id& object) {
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->exists<Id>(object);
}
- template<class Holder, class Tag>
- static Data<Tag> get(const Holder& holder, Data<Tag>&& dataDefault)
- {
- if (! exists<Holder, Tag>(holder)){
- return dataDefault;
+ template<class Tag, class Id>
+ static Data<Tag>& get(const Id& object){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->get<Id>(object);
+ }
+
+ template<class Tag, class Id>
+ static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ return self->get<Id>(object, dataDefault);
+ }
+
+ template<class Tag, class Id>
+ static void put(const Id& object, Data<Tag> data){
+ assert(AttachmentsDict<Tag>::key < __storage.size());
+ assert(__storage.at(AttachmentsDict<Tag>::key));
+
+ IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
+ self->put<Id>(object, data);
+ }
+
+ template<class Tag>
+ static void init(){
+ unsigned int keyStorage = AttachmentsDict<Tag>::key;
+ if (keyStorage+1 > __storage.size()){
+ __storage.resize(keyStorage + 1, nullptr);
}
- const unsigned int key = AttachmentsDict<Tag>::key;
- Attachments* self = AttachmentsStorage<Holder>::get(holder);
-
- return detail::__unwrap<Data<Tag>>(self->get(key));
+ __storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
}
-
- 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);
+
+ template<class Tag>
+ static void init(IAttachmentsContainer<Data<Tag>>* container){
+ unsigned int keyStorage = AttachmentsDict<Tag>::key;
+ if (keyStorage+1 > __storage.size()){
+ __storage.resize(keyStorage + 1, nullptr);
+ }
+
+ __storage[keyStorage] = container;
}
+};
- 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_
+#endif //_XREATE_ATTACHMENTS_H_
\ No newline at end of file
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index 6434235..65ff3fb 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,275 +1,275 @@
#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::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
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();
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->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
ClaspLayer::getScopesCount() const{
return __registryScopes.size();
}
SymbolPacked
ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
{
- SymbolPacked result(symbol.identifier, pack(symbol.scope));
+ SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
ClaspLayer::unpack(const SymbolPacked& symbol)
{
- return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
+ return Symbol{ScopedSymbol{symbol.identifier, symbol.version}, __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);
}
}
\ No newline at end of file
diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h
index 6961026..1bfe432 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,230 +1,233 @@
#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;
+ VNameId identifier;
+ VariableVersion version;
ScopePacked scope;
bool categoryTransient;
SymbolPacked(): categoryTransient(false){}
- SymbolPacked(VID i, ScopePacked s, bool isTransient = false): identifier(i), scope(s), categoryTransient(isTransient){}
+ SymbolPacked(ScopedSymbol i, ScopePacked s, bool isTransient = false): identifier(i.id), version(i.version), scope(s), categoryTransient(isTransient){}
+ SymbolPacked(VNameId symbolId, VariableVersion symbolVersion, ScopePacked symbolScope, bool isTransient = false)
+ : identifier(symbolId), version(symbolVersion), scope(symbolScope), categoryTransient(isTransient){}
};
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 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));
+ auto result = ClaspLayer::parse<unsigned int, unsigned int, unsigned int>(atom);
+ return SymbolPacked(std::get<0>(result), std::get<1>(result), std::get<2>(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
\ No newline at end of file
diff --git a/cpp/src/compilation/advanced.cpp b/cpp/src/compilation/advanced.cpp
index d49ede8..d5183a8 100644
--- a/cpp/src/compilation/advanced.cpp
+++ b/cpp/src/compilation/advanced.cpp
@@ -1,432 +1,403 @@
/*
* File: InstructionsAdvanced.cpp
* Author: pgess
*
* Created on June 26, 2016, 6:00 PM
*/
-#include <compilation/transformations.h>
+//#include <compilation/transformations.h>
#include "compilation/advanced.h"
#include "compilation/containers.h"
+#include "compilation/transformersaturation.h"
#include "query/context.h"
#include "query/containers.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::AbstractCodeScopeUnit* 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::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT
//initialization
- std::string varIn = expr.getOperands()[0].getValueString();
- Symbol symbolIn = scope->scope->findSymbol(varIn);
+ Symbol symbolIn = Attachments::get<Symbol>(expr.getOperands()[0]);
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);
+ compilation::AbstractCodeScopeUnit* 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);
+ stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
Advanced::compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string hintRetVar) {
EXPAND_CONTEXT
UNUSED(function);
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
llvm::Value *pEl = llvm->builder.CreateGEP(aggregate, 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: validPtr for `aggregate`
// SECTIONTAG validptr exception
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());
+ Symbol varInSymbol = Attachments::get<Symbol>(fold.getOperands()[0]);
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();
+ std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
+
+
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::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_body", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_after", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_next", function->raw);
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
- llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
+ llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, varAccum);
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
itLoop->addIncoming(rangeBegin, blockBeforeLoop);
+ // * loop checks
+ Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
+ llvm->builder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
+
// * loop body
- llvm->builder.SetInsertPoint(blockBody);
+ llvm->builder.SetInsertPoint(blockLoopBody);
CodeScope* scopeLoop = fold.blocks.front();
- compilation::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
+ compilation::AbstractCodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
+ // * Loop saturation checks
+ bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
+ llvm::BasicBlock* blockSaturation = llvm->builder.GetInsertBlock();
+ if (!flagSaturationTriggered){
+ llvm->builder.CreateBr(blockNext);
+ }
+
// * computing next iteration state
+ llvm->builder.SetInsertPoint(blockNext);
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:
+ // * finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
+ if (!flagSaturationTriggered){
+ return accum;
+ }
- return accum;
+ llvm::PHINode* result = llvm->builder.CreatePHI(accumInit->getType(), 2);
+ result->addIncoming(accum, blockLoop);
+ result->addIncoming(accumNext, blockSaturation);
+ return result;
}
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::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf", function->raw);
+ llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_next", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_post", function->raw);
+ std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
- llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, NAME("accum"));
+ llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, accumName);
accum->addIncoming(accumInit, blockBeforeLoop);
// * loop body
- llvm->builder.SetInsertPoint(blockBody);
CodeScope* scopeLoop = fold.blocks.front();
- compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
+ compilation::AbstractCodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(accum, move(accumName));
Value* accumNext = unitLoop->compile();
+ // * Loop saturation checks
+ bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
+ assert(flagSaturationTriggered);
+
// * computing next iteration state
+ llvm->builder.SetInsertPoint(blockNext);
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;
+ return accumNext;
}
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::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();
+ blockTrue = builder.GetInsertBlock();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
+ blockFalse = builder.GetInsertBlock();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
- llvm::PHINode *ret = builder.CreatePHI(tyResultType, 2, NAME("if"));
+ llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 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(function);
assert(exprSwitch.operands.size() >= 2);
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;
}
//TODO recognize cases to make const arrays/stored in global mem/stack alloced.
llvm::Value*
Advanced::compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
AST* root = context.pass->man->root;
const size_t& length = expr.getOperands().size();
const Expression& expression = expr;
llvm::Value* zero = ConstantInt::get(tyNum, 0);
llvm::Value* one = ConstantInt::get(tyNum, 1);
ExpandedType typAggrExpanded = root->expandType(expression.type);
assert(typAggrExpanded->__operator == TypeOperator::ARRAY);
llvm::Type* typEl = llvm->toLLVMType(ExpandedType(typAggrExpanded->__operands[0]));
ArrayType* typAggr = (ArrayType*) llvm::ArrayType::get(typEl, length);
llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), length, false), hintRetVar);
const std::vector<Expression>& operands = expression.getOperands();
llvm::Value* addrOperand = llvm->builder.CreateGEP(typAggr, list, ArrayRef<Value *>(std::vector<Value*>{zero, zero}));
llvm->builder.CreateStore(scope->process(operands.front()), addrOperand) ;
for (auto i=++operands.begin(); i!=operands.end(); ++i){
addrOperand = llvm->builder.CreateGEP(typEl, addrOperand, ArrayRef<Value *>(std::vector<Value*>{one}));
llvm->builder.CreateStore(scope->process(*i), addrOperand) ;
}
return list;
// Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
// l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
}
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/advanced.h b/cpp/src/compilation/advanced.h
index 373e825..5bef2ef 100644
--- a/cpp/src/compilation/advanced.h
+++ b/cpp/src/compilation/advanced.h
@@ -1,47 +1,49 @@
/*
* File: InstructionsAdvanced.h
* Author: pgess
*
* Created on June 26, 2016, 6:00 PM
*/
#ifndef INSTRUCTIONSADVANCED_H
#define INSTRUCTIONSADVANCED_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include <vector>
namespace xreate {
namespace compilation {
class Advanced {
public:
Advanced(compilation::Context ctx);
llvm::Value* compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string ident = "");
llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
llvm::Value* compileMapSolidOutput(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
llvm::Value* compileFoldInf(const Expression& fold, const std::string& ident="");
+
+ //DISABLEDFEATURE Context Loop
llvm::Value* compileLoopContext(const Expression& expression, const std::string& hintRetVar);
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
llvm::Value* compileConstantStringAsPChar(const std::string &data, const std::string& hintRetVar);
llvm::Value* compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar="");
private:
compilation::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif /* INSTRUCTIONSADVANCED_H */
diff --git a/cpp/src/compilation/containers.cpp b/cpp/src/compilation/containers.cpp
index df7c9e3..f60f5ed 100644
--- a/cpp/src/compilation/containers.cpp
+++ b/cpp/src/compilation/containers.cpp
@@ -1,195 +1,195 @@
#include "compilation/containers.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
Iterator*
Iterator::create(xreate::compilation::Context context, const xreate::Symbol& var){
const Implementation& data = Query::queryImplementation(var);
switch(data.impl){
case ON_THE_FLY:
return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
case SOLID:
return new IteratorForward<SOLID>(context, var, data.extract<SOLID>());
default: assert(true);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::begin() {
switch(sourceDecl.op) {
case xreate::Operator::LIST:
{
sourceRawType = llvm::Type::getInt32Ty(llvm::getGlobalContext());
return llvm::ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 0);
};
case xreate::Operator::LIST_RANGE:{
assert(sourceDecl.operands.size()==2);
llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
sourceRawType = result->getType();
return result;
};
default: break;
}
if (linkedlist){
llvm::Value* result = sourceUnit->process(sourceDecl);
sourceRawType = result->getType();
return result;
}
assert(false);
}
llvm::Value*
IteratorForward<ON_THE_FLY>::end(){
switch(sourceDecl.op) {
case xreate::Operator::LIST: {
size_t idLast = sourceDecl.operands.size() - 1;
return ConstantInt::get(sourceRawType, idLast);
}
case xreate::Operator::LIST_RANGE: {
assert(sourceDecl.operands.size() == 2);
llvm::Value* valueEndOfRange = sourceUnit->process(sourceDecl.operands.at(1));
llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1);
return llvm->builder.CreateAdd(valueEndOfRange, valueConstOne);
};
default: break;
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::get(Value* index,const std::string& hintRetVar){
- const Expression& currentDecl = CodeScope::findDeclaration(current);
+ const Expression& currentDecl = CodeScope::getDeclaration(current);
switch (currentDecl.op) {
case xreate::Operator::LIST: {
//TODO re check is it right scope(source) to compile currentDecl. Provide unittests.
- llvm::Value* currentValue = sourceUnit->compileSymbol(current);
+ llvm::Value* currentValue = sourceUnit->processSymbol(current);
return xreate::compilation::Advanced(context).compileArrayIndex(currentValue, std::vector<Value *>{index});
};
case xreate::Operator::LIST_RANGE: {
return index;
};
case xreate::Operator::MAP: {
assert(currentDecl.getOperands().size()==1);
assert(currentDecl.bindings.size());
assert(currentDecl.blocks.size());
CodeScope* scopeLoop = currentDecl.blocks.front();
- const std::string& varIn = currentDecl.getOperands()[0].getValueString();
std::string varEl = currentDecl.bindings[0];
- const Symbol& symbIn = current.scope->findSymbol(varIn);
+ const Symbol& symbIn = Attachments::get<Symbol>(currentDecl.getOperands()[0]);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
Value* elIn = it->get(index, varEl);
- compilation::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
+ compilation::AbstractCodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(elIn, std::move(varEl));
return unitLoop->compile();
}
case xreate::Operator::NONE: {
//TODO review iterator determination strategy for case of Expression::BINDING
assert(currentDecl.__state==Expression::IDENT);
- const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
+
+ const Symbol& symbIn = Attachments::get<Symbol>(currentDecl);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
return it->get(index);
};
default: break;
}
if (linkedlist){
return index;
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::advance(Value* index, const std::string& hintRetVar){
switch(sourceDecl.op)
{
case xreate::Operator::LIST:
case xreate::Operator::LIST_RANGE:
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
default: break;
}
if (linkedlist){
- ExpandedType tySource = llvm->ast->expandType(CodeScope::findDeclaration(source).type);
+ ExpandedType tySource = llvm->ast->expandType(CodeScope::getDeclaration(source).type);
assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
assert(tySource->__operands.size());
return xreate::compilation::Advanced(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
}
assert(false && "Unknown declaration");
return nullptr;
}
//const ImplementationRec<ON_THE_FLY>& implementation
IteratorForward<SOLID>::IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation)
- : Iterator(), llvm(ctx.pass->man->llvm), __length(implementation.size)
+ : Iterator(), __length(implementation.size), llvm(ctx.pass->man->llvm)
{
- __container = ctx.function->getScopeUnit(symbolContainer.scope)->compileSymbol(symbolContainer);
+ __container = ctx.function->getScopeUnit(symbolContainer.scope)->processSymbol(symbolContainer);
}
llvm::Value*
IteratorForward<SOLID>::begin(){
//0
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0);
}
llvm::Value*
IteratorForward<SOLID>::end(){
//length
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), __length);
}
llvm::Value*
IteratorForward<SOLID>::get(llvm::Value* index,const std::string& hintRetVar){
//GEP[index]]
llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::Value* pResult = llvm->builder.CreateGEP(__container, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), index}));
return llvm->builder.CreateLoad(pResult, hintRetVar);
}
llvm::Value*
IteratorForward<SOLID>::advance(llvm::Value* index, const std::string& hintRetVar){
//index + 1
llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm::getGlobalContext());
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(tyNum, 1), hintRetVar);
}
diff --git a/cpp/src/compilation/containers.h b/cpp/src/compilation/containers.h
index 222be75..71815a7 100644
--- a/cpp/src/compilation/containers.h
+++ b/cpp/src/compilation/containers.h
@@ -1,80 +1,80 @@
#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "compilation/advanced.h"
#include "query/context.h"
#include "query/containers.h"
namespace xreate {
namespace containers {
using namespace llvm;
class Iterator{
public :
virtual llvm::Value* begin() =0;
virtual llvm::Value* end() = 0;
virtual llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") = 0;
virtual llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="")=0;
virtual ~Iterator(){};
static Iterator* create(xreate::compilation::Context context, const xreate::Symbol& var);
};
template<ImplementationType I>
class IteratorForward;
template<>
class IteratorForward<ON_THE_FLY> : public Iterator {
private:
LLVMLayer* llvm;
const xreate::Symbol current;
const Symbol source;
const ImplementationLinkedList linkedlist;
CodeScope* const sourceScope;
//TODO initialize and mark as const (three fields)
- compilation::CodeScopeUnit* sourceUnit;
+ compilation::AbstractCodeScopeUnit* sourceUnit;
compilation::FunctionUnit* function; //TODO is used somewhere?
const Expression& sourceDecl;
compilation::Context context;
llvm::Type* sourceRawType =nullptr;
public:
IteratorForward(const compilation::Context& ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
: llvm(ctx.pass->man->llvm),
current(s),
source(implementation.source),
linkedlist(source),
sourceScope(source.scope),
- sourceUnit(new compilation::CodeScopeUnit(source.scope, ctx.function, ctx.pass)),
- sourceDecl(CodeScope::findDeclaration(source)),
+ sourceUnit(ctx.function->getScopeUnit(source.scope)),
+ sourceDecl(CodeScope::getDeclaration(source)),
context(ctx)
{}
llvm::Value* begin() override;
llvm::Value* end() override;
llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};
template<>
class IteratorForward<SOLID>: public Iterator{
size_t __length;
llvm::Value* __container;
LLVMLayer* llvm;
public:
IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation);
llvm::Value* begin() override;
llvm::Value* end() override;
llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};
}}
#endif //CODEINSTRUCTIONS_H
diff --git a/cpp/src/compilation/scopedecorators.h b/cpp/src/compilation/scopedecorators.h
new file mode 100644
index 0000000..612d68a
--- /dev/null
+++ b/cpp/src/compilation/scopedecorators.h
@@ -0,0 +1,123 @@
+/*
+ * File: scopedecorators.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on February 24, 2017, 11:35 AM
+ */
+
+#ifndef SCOPEDECORATORS_H
+#define SCOPEDECORATORS_H
+
+#include "ast.h"
+#include "compilation/targetinterpretation.h"
+#include "compilation/versions.h"
+#include "compilation/transformations.h"
+
+namespace xreate {
+
+class CompilePass;
+
+namespace compilation {
+
+class AbstractCodeScopeUnit;
+class FunctionUnit;
+
+template<class Parent>
+class CachedScopeDecorator: public Parent{
+ typedef CachedScopeDecorator<Parent> SELF;
+
+public:
+ CachedScopeDecorator(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+
+ void reset(){
+ __rawVars.clear();
+ }
+
+ void bindArg(llvm::Value* value, std::string&& alias)
+ {
+ //ensure existence of an alias
+ assert(Parent::scope->__identifiers.count(alias));
+
+ //memorize new value for an alias
+ ScopedSymbol id{Parent::scope->__identifiers.at(alias), VERSION_NONE};
+ __rawVars[id] = value;
+ }
+
+ void bindArg(llvm::Value* value, const ScopedSymbol& s) {
+ __rawVars[s] = value;
+ }
+
+ llvm::Value* compile(const std::string& hintBlockDecl="") override{
+ if (__rawVars.count(ScopedSymbol::RetSymbol)){
+ return __rawVars[ScopedSymbol::RetSymbol];
+ }
+
+ return Parent::compile(hintBlockDecl);
+ }
+
+ llvm::Value*
+ processSymbol(const Symbol& s, std::string hintRetVar) override{
+ CodeScope* scope = s.scope;
+ SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(scope));
+
+ if (self->__rawVars.count(s.identifier)){
+ return self->__rawVars[s.identifier];
+ }
+
+ //Declaration could be overriden
+ Expression declaration = CodeScope::getDeclaration(s);
+ if (!declaration.isDefined()){
+ if (self->__declarationsOverriden.count(s.identifier)){
+ declaration = self->__declarationsOverriden[s.identifier];
+
+ } else {
+ assert(false); //in case of binding there should be raws provided.
+ }
+ }
+
+ return self->__rawVars[s.identifier] = Parent::processSymbol(s, hintRetVar);
+ }
+
+ void
+ overrideDeclaration(const Symbol binding, Expression&& declaration){
+ SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(binding.scope));
+
+ self->__declarationsOverriden.emplace(binding.identifier, std::move(declaration));
+ }
+
+private:
+ std::unordered_map<ScopedSymbol, Expression> __declarationsOverriden;
+ std::unordered_map<ScopedSymbol,llvm::Value*> __rawVars;
+
+};
+
+typedef CachedScopeDecorator<
+ compilation::TransformationsScopeDecorator<
+ compilation::InterpretationScopeDecorator<
+ compilation::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>>
+
+ DefaultScopeUnit;
+
+} //end of compilation namespace
+
+struct CachedScopeDecoratorTag;
+struct VersionsScopeDecoratorTag;
+
+template<>
+struct DecoratorsDict<CachedScopeDecoratorTag>{
+ typedef compilation::CachedScopeDecorator<
+ compilation::TransformationsScopeDecorator<
+ compilation::InterpretationScopeDecorator<
+ compilation::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>> result;
+};
+
+template<>
+struct DecoratorsDict<VersionsScopeDecoratorTag>{
+ typedef compilation::VersionsScopeDecorator<
+ compilation::BasicCodeScopeUnit> result;
+};
+
+} //end of xreate
+
+#endif /* SCOPEDECORATORS_H */
+
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index b50bf13..2969498 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,446 +1,432 @@
/*
* 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 "compilation/scopedecorators.h"
+
#include <boost/scoped_ptr.hpp>
#include <iostream>
+#include <clang/AST/DeclBase.h>
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);
+ Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), VERSION_NONE}, scopeBody};
const std::string& idAccum = expression.bindings[1];
llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
- compilation::CodeScopeUnit* unitBody = context.function->getScopeUnit(scopeBody);
+ auto unitBody = Decorators<CachedScopeDecoratorTag>::getInterface(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->overrideBinding(exprElement, nameEl);
- unitBody->overrideDeclaration(symbolEl, move(exprElement));
+ unitBody->overrideDeclaration(symbEl, 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;
+ AbstractCodeScopeUnit* 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);
+ const InterpretationData& data = Attachments::get<InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE){
return compileHybrid(data.op, expression, context);
}
Expression result = process(expression);
- return context.scope->processLowlevel(result);
+ return context.scope->process(result);
}
Expression
InterpretationScope::process(const Expression& expression){
switch (expression.__state){
- case Expression::VARIANT:
case Expression::INVALID:
assert(false);
+ case Expression::VARIANT:
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:{
- const std::string &ident = expression.getValueString();
-
- Symbol s = scope->findSymbol(ident);
+ Symbol s = Attachments::get<Symbol>(expression);
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);
InterpretationFunction* 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()));
-
+ const Expression& exprKey = process(expression.operands[1]);
+ const Expression& exprData = process(expression.operands[0]);
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->overrideBinding(exprInput.getOperands()[i], argEl);
body->overrideBinding(accum, argAccum);
accum = body->processScope();
}
return accum;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
InterpretationFunction*
TargetInterpretation::getFunction(FunctionUnit* unit){
if (__dictFunctionsByUnit.count(unit)) {
return __dictFunctionsByUnit.at(unit);
}
InterpretationFunction* f = new InterpretationFunction(unit->function, this);
__dictFunctionsByUnit.emplace(unit, f);
assert(__functions.emplace(unit->function.id(), f).second);
return f;
}
PIFunction*
TargetInterpretation::getFunction(PIFSignature&& sig){
auto f = __pifunctions.find(sig);
if (f != __pifunctions.end()){
return f->second;
}
PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this);
__pifunctions.emplace(move(sig), result);
assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c){
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, {ANY, NONE});
-
- return (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
-}
-
InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
: Function<TargetInterpretation>(function, target)
{}
Expression
InterpretationFunction::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)));
}
return body->processScope();
}
// Partial function interpretation
typedef BasicFunctionDecorator PIFunctionUnitParent;
class PIFunctionUnit: public PIFunctionUnitParent{
public:
PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
: PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id)
{}
protected:
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: argumentsActual){
- Symbol arg = entry->findSymbol(entry->__bindings[no]);
+ VNameId argId = entry->__identifiers.at(entry->__bindings.at(no));
+ ScopedSymbol arg{argId, VERSION_NONE};
- signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations[arg.identifier].type)));
+ signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type)));
}
return signature;
}
llvm::Function::arg_iterator prepareBindings(){
CodeScope* entry = PIFunctionUnitParent::function->__entry;
- CodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
+ AbstractCodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
for(size_t no: argumentsActual){
- Symbol arg = entry->findSymbol(entry->__bindings[no]);
+ ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), VERSION_NONE};
- entryCompilation->__rawVars[arg.identifier] = &*fargsI;
- fargsI->setName(entry->__bindings[no]);
+ entryCompilation->bindArg(&*fargsI, arg);
+ fargsI->setName(entry->__bindings.at(no));
++fargsI;
}
return fargsI;
}
virtual std::string prepareName(){
return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
}
private:
std::set<size_t> argumentsActual;
size_t __id;
};
PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
: InterpretationFunction(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();
+ auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(functionUnit->getEntry());
InterpretationScope* entryIntrp = InterpretationFunction::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]));
+
+ VNameId argId = entry->__identifiers.at(entry->__bindings[no]);
+ Symbol argSymbol{ScopedSymbol{argId, VERSION_NONE}, entry};
+ entryUnit->overrideDeclaration(argSymbol, Expression(signatureInstance.bindings[sigNo]));
++sigNo;
}
}
}
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;
}
}}
\ No newline at end of file
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 0ef32e7..7b7acdd 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,116 +1,134 @@
/*
* 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 "pass/compilepass.h"
#include "compilation/targets.h"
-#include "transformations.h"
#include "pass/interpretationpass.h"
namespace xreate{ namespace compilation {
class TargetInterpretation;
class InterpretationScope;
class InterpretationFunction;
template <>
struct TargetInfo<TargetInterpretation> {
typedef Expression Result;
typedef InterpretationScope Scope;
typedef InterpretationFunction 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);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
};
class InterpretationFunction: public Function<TargetInterpretation>{
public:
InterpretationFunction(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 PIFunctionUnit;
class PIFunction: public InterpretationFunction{
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{
+class TargetInterpretation: public Target<TargetInterpretation>{
public:
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:
InterpretationFunction* getFunction(FunctionUnit* unit);
PIFunction* getFunction(PIFSignature&& sig);
private:
std::map<PIFSignature, PIFunction*> __pifunctions;
std::map<FunctionUnit*, InterpretationFunction*> __dictFunctionsByUnit;
//self:
public:
CompilePass* pass;
llvm::Value* compile(const Expression& expression, const Context& ctx);
private:
InterpretationScope* transformContext(const Context& c);
};
+template<class Parent>
+class InterpretationScopeDecorator: public Parent{
+public:
+ InterpretationScopeDecorator(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+
+ virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl){
+ const InterpretationData& data = Attachments::get<InterpretationData>(expr, {ANY, NONE});
+ bool flagInterpretationEligible = (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
+
+ if (flagInterpretationEligible){
+ Context ctx{this, this->function, this->pass};
+ return Parent::pass->targetInterpretation->compile(expr, ctx);
+ }
+
+ return Parent::process(expr, hintVarDecl);
+ }
+};
+
+
+
+} //end of compilation
+
+struct InterpretationScopeDecoratorTag;
+
+} //end of xreate
+#endif /* TARGETSTATIC_H */
-}}
-#endif /* TARGETSTATIC_H */
\ No newline at end of file
+//transformers:
+// template<>
+// struct TransformerInfo<TargetInterpretation> {
+// static const int id = 1;
+// };
\ No newline at end of file
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
index f6b47bb..a871d44 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,161 +1,161 @@
/*
* 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);
+ const Expression& declaration = CodeScope::getDeclaration(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->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
overrideBinding(typename TargetInfo<ConcreteTarget>::Result arg, const std::string& name){
assert(scope->__identifiers.count(name));
- VID id = scope->__identifiers.at(name);
+ ScopedSymbol id{scope->__identifiers.at(name), VERSION_NONE};
__bindings[id] = arg;
//reset the result if any:
raw.reset();
}
protected:
Function<ConcreteTarget>* function=0;
- std::map<VID, typename TargetInfo<ConcreteTarget>::Result> __bindings;
+ std::map<ScopedSymbol, 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) {}
virtual ~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=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, unit);
return unit;
}
return __functions.at(id);
}
AST* ast;
virtual ~Target(){
for (const auto& entry: __functions){
delete entry.second;
}
}
protected:
std::map<unsigned int, ConcreteFunction*> __functions;
};
}}
#endif /* TARGETABSTRACT_H */
\ No newline at end of file
diff --git a/cpp/src/compilation/transformations.cpp b/cpp/src/compilation/transformations.cpp
index d77ca83..1588af8 100644
--- a/cpp/src/compilation/transformations.cpp
+++ b/cpp/src/compilation/transformations.cpp
@@ -1,143 +1,29 @@
-/*
- * File: Transformations.cpp
- * Author: pgess
- *
- * Created on June 18, 2016, 6:23 PM
+/*
+ * transformation.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on March 27, 2017, 4:04 PM
*/
-#include "compilation/transformations.h"
-#include "pass/compilepass.h"
-#include "llvmlayer.h"
-#include <llvm/IR/Value.h>
+#include "transformations.h"
-using namespace llvm;
-
-namespace xreate { namespace compilation {
-
-Transformations::Transformations(CompilePass* passCompilation): pass(passCompilation) {
-}
-
-void
-Transformations::subscribe(const std::string& annotation, int handler){
- __subscriptions.emplace(annotation, handler);
-}
-
-bool
-Transformations::isAcceptable(const Expression& expression){
- //check subscription based on expression attachments
- if (Attachments::get<Expression, Transformations>(expression, {false, 0}).flagSubscribed){
- return true;
- }
-
- //subscription based on expression annotations;
- if (expression.tags.size() == 0) return false;
-
- for (auto tag: expression.tags) {
- if (__subscriptions.count(tag.first)){
- return true;
- }
- }
-
- return false;
-}
-
-Expression
-Transformations::transform(const Expression& expression, const Context& ctx){
- Expression result = expression;
-
- for (auto handler: getAppropriateTransformers(expression)){
- result = handler->transform(result, ctx);
- }
-
- return result;
-}
-
-llvm::Value*
-Transformations::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
- for (auto handler: getAppropriateTransformers(expression)){
- raw = handler->transform(expression, raw, ctx);
- }
-
- return raw;
-}
+namespace xreate { namespace compilation {
std::list<Transformer*>
-Transformations::getAppropriateTransformers(const Expression& expression){
-
+TransformationsManager::getRelevantTransformers(const Expression& expression){
std::list<Transformer*> result;
-
+
for (auto tag: expression.tags) {
if (__subscriptions.count(tag.first)){
auto handlers = __subscriptions.equal_range(tag.first);
-
- for (auto handlerIt=handlers.first; handlerIt!= handlers.second; ++handlerIt){
- Transformer* handler = __transformers[handlerIt->second];
-
- if (handler->isAcceptable(expression)){
- result.push_back(handler);
- }
+
+ for (auto handler = handlers.first; handler != handlers.second; ++handler){
+ result.push_back(__transformers[handler->second]);
}
}
}
-
- auto subscriberInternal = Attachments::get<Expression, Transformations>(expression, {false, 0});
- if (subscriberInternal.flagSubscribed){
- result.push_back(__transformers[subscriberInternal.subscriberId]);
- }
-
- return result;
-}
-TransformerSaturation::TransformerSaturation(Transformations* man)
- : __man(man) {
-
- man->subscribe("break", TransformerInfo<TransformerSaturation>::id);
-}
-
-bool
-TransformerSaturation::isAcceptable(const Expression& expression){
- return true;
-}
-
-bool
-TransformerSaturation::exists() const{
- return __block != nullptr;
-}
-
-llvm::Value*
-TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
- __block = __man->pass->man->llvm->builder.GetInsertBlock();
-
- return raw;
-}
-
-llvm::BasicBlock*
-TransformerSaturation::getBlock() const{
- return __block;
-}
-
-void
-TransformerSaturation::inject(llvm::BasicBlock* blockAllocation, llvm::BasicBlock* blockExit, compilation::Context context){
- llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
- llvm::Value* valueConstOne = llvm::ConstantInt::get(tyInt1, 1);
- llvm::Value* valueConstFalse = llvm::ConstantInt::get(tyInt1, 0);
-
- //allocation of saturation flag
- IRBuilder<> builderAlloca(blockAllocation, blockAllocation->getFirstInsertionPt());
- llvm::Value* flagSaturation = builderAlloca.CreateAlloca(tyInt1, valueConstOne, "flagSaturation");
- builderAlloca.CreateStore(valueConstFalse, flagSaturation, true);
-
- //set up saturation flag
- llvm::BasicBlock* blockSaturation = __block;
- IRBuilder<> builderSaturation(blockSaturation, blockSaturation->getFirstInsertionPt());
- builderSaturation.CreateStore(valueConstOne, flagSaturation, true);
-
- //check saturation flag:
- //TODO remove blockContinue, receive from caller block to continue.
- llvm::BasicBlock *blockContinue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "continue", context.function->raw);
- context.pass->man->llvm->builder.CreateCondBr(context.pass->man->llvm->builder.CreateLoad(flagSaturation), blockExit, blockContinue);
-
- context.pass->man->llvm->builder.SetInsertPoint(blockContinue);
+ return result;
}
-}}
\ No newline at end of file
+} } //namespace xreate
\ No newline at end of file
diff --git a/cpp/src/compilation/transformations.h b/cpp/src/compilation/transformations.h
index daec0bf..4350147 100644
--- a/cpp/src/compilation/transformations.h
+++ b/cpp/src/compilation/transformations.h
@@ -1,119 +1,111 @@
/*
- * File: Transformations.h
- * Author: pgess
+ * File: transformations.h
+ * Author: pgess <v.melnychenko@xreate.org>
*
- * Created on June 18, 2016, 6:23 PM
+ * Created on March 25, 2017, 9:04 PM
*/
#ifndef TRANSFORMATIONS_H
#define TRANSFORMATIONS_H
-#include "ast.h"
#include "pass/compilepass.h"
-#include "attachments.h"
-
-namespace llvm {
- class BasicBlock;
-}
namespace xreate { namespace compilation {
-
- class Transformer{
- public:
- virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx)=0;
- virtual Expression transform(const Expression& expression, const Context& ctx){return expression;}
- virtual bool isAcceptable(const Expression& expression)=0;
-
- virtual ~Transformer(){};
- };
-
- class TransformerSaturation: public Transformer{
- public:
- llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx);
- bool isAcceptable(const Expression& expression);
- TransformerSaturation(Transformations*);
- llvm::BasicBlock* getBlock() const;
- bool exists() const;
- void inject(llvm::BasicBlock* blockAllocation, llvm::BasicBlock* blockExit, compilation::Context context);
-
- private:
- llvm::BasicBlock* __block = nullptr;
- Transformations* __man;
- };
+template <class TransformerType>
+struct TransformerInfo {
+ //static const unsigned int id = 1; (current vacant id)
+};
- template <class TransformerType>
- struct TransformerInfo {
- //static const int id = 1; (next vacant id)
- };
+class Transformer{
+public:
+ virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx)=0;
+ virtual ~Transformer(){};
+};
+
+class TransformationsManager {
+public:
+ std::list<Transformer*> getRelevantTransformers(const Expression& expression);
- template <>
- struct TransformerInfo<TransformerSaturation> {
- static const int id = 0;
- };
- class Transformations;
+ template<class TransformerType>
+ void registerTransformer(const std::string& annotation, TransformerType* t){
+ const int id = TransformerInfo<TransformerType>::id;
+
+ assert(!__transformers.count(id));
+ __transformers[id] = t;
+ __subscriptions.emplace(annotation, id);
+ }
- struct SubscriberInfo{
- bool flagSubscribed;
- int subscriberId;
- };
+ template<class TransformerType>
+ void unregisterTransformer(const std::string& annotation, TransformerType* t){
+ const unsigned int id = TransformerInfo<TransformerType>::id;
+
+ auto range = __subscriptions.equal_range(annotation);
+ const auto entry = make_pair(annotation, id);
+ __subscriptions.erase(std::find_if(range.first, range.second, [id](const auto& el){return el.second == id;}));
+ __transformers.erase(id);
+ }
- class Transformations: public Transformer {
- public:
- xreate::CompilePass* pass;
-
- bool isAcceptable(const Expression& expression);
- llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
- Expression transform(const Expression& expression, const Context& ctx) override;
+ template<class TransformerType>
+ TransformerType* update(TransformerType* newInstance){
+ const int id = TransformerInfo<TransformerType>::id;
- Transformations(CompilePass*);
- void subscribe(const std::string& annotation, int handler);
+ Transformer* oldInstance = __transformers[id];
+ __transformers[id] = newInstance;
- template<class TransformerType>
- void registerTransformer(TransformerType* t){
- const int id = TransformerInfo<TransformerType>::id;
-
- __transformers[id] = t;
- }
+ return static_cast<TransformerType*>(oldInstance);
+ }
+
+ template<class TransformerType>
+ bool exists(){
+ const int id = TransformerInfo<TransformerType>::id;
- template<class Holder, class TransformerType>
- static void subscribe(const Holder& holder){
- //assert(! Attachments::exists<Holder, Transformations>());
-
- const int id = TransformerInfo<TransformerType>::id;
-
- if (Attachments::exists<Holder, Transformations>(holder)){
- const int idOld = Attachments::get<Holder, Transformations>(holder).subscriberId;
- assert(idOld == id);
- return;
- }
+ return __transformers.count(id);
+ }
- Attachments::put<Holder, Transformations>(holder, {true, id});
- }
+ template <class TransformerType>
+ TransformerType* get(){
+ const int id = TransformerInfo<TransformerType>::id;
+ return static_cast<TransformerType*>(__transformers.at(id));
+ }
+
+private:
+ std::map<unsigned int, Transformer*> __transformers;
+ std::multimap<std::string, unsigned int> __subscriptions;
+};
- template <class TransformerType>
- TransformerType* get(){
- const int id = TransformerInfo<TransformerType>::id;
- return static_cast<TransformerType*>(__transformers.at(id));
- }
+template <class Parent>
+class TransformationsScopeDecorator: public Transformer, public Parent {
+ // SCOPE DECORATOR PART
+public:
+ TransformationsScopeDecorator(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
+ : Parent(codeScope, f, compilePass){}
+
+ virtual llvm::Value*
+ process(const Expression& expr, const std::string& hintVarDecl=""){
+ llvm::Value* result = Parent::process(expr, hintVarDecl);
- private:
- std::map<int, Transformer*> __transformers;
- std::multimap<std::string, int> __subscriptions;
+ return transform(expr, result, Context{this, Parent::function, Parent::pass});
+ }
+
+ // TRANSFORMER PART
+public:
+ virtual llvm::Value*
+ transform(const Expression& expression, llvm::Value* raw, const Context& ctx) {
+ llvm::Value* result = raw;
+ TransformationsManager* man = Parent::pass->managerTransformations;
- std::list<Transformer*> getAppropriateTransformers(const Expression& expression);
- };
-}}
-
-namespace xreate {
- template<>
- struct AttachmentsDict<compilation::Transformations>
- {
- typedef xreate::compilation::SubscriberInfo Data;
- static const unsigned int key = 4;
- };
-}
+ if (expression.tags.size())
+ for (Transformer* handler: man->getRelevantTransformers(expression)){
+ result = handler->transform(expression, result, ctx);
+ }
+
+ return result;
+ }
+};
+} }
+
#endif /* TRANSFORMATIONS_H */
diff --git a/cpp/src/compilation/transformersaturation.cpp b/cpp/src/compilation/transformersaturation.cpp
new file mode 100644
index 0000000..4ea90d0
--- /dev/null
+++ b/cpp/src/compilation/transformersaturation.cpp
@@ -0,0 +1,77 @@
+/*
+ * transformersaturation.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on March 25, 2017, 10:06 PM
+ */
+
+#include "transformersaturation.h"
+#include "llvmlayer.h"
+
+using namespace llvm;
+
+namespace xreate { namespace compilation {
+
+TransformerSaturation::TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager)
+ : man(manager), blockAllocation(allocationBlock){
+
+ llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
+
+ constTrue = llvm::ConstantInt::get(tyInt1, 1);
+ constFalse = llvm::ConstantInt::get(tyInt1, 0);
+
+ if (man->exists<TransformerSaturation>()){
+ oldInstance = man->update(this);
+
+ } else {
+ man->registerTransformer("break", this);
+ }
+}
+
+TransformerSaturation::~TransformerSaturation(){
+ if (oldInstance) {
+ man->update(oldInstance);
+
+ } else {
+ man->unregisterTransformer("break", this);
+ }
+}
+
+llvm::Value*
+TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
+ processBreak(ctx);
+
+ return raw;
+}
+
+
+void
+TransformerSaturation::processBreak(const Context& ctx){
+ allocateFlag(ctx);
+
+ //show the saturation flag
+ llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
+ builder.CreateStore(constTrue, flagSaturation, true);
+}
+
+void
+TransformerSaturation::allocateFlag(const Context& ctx){
+ //allocation of saturation flag
+ llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ IRBuilder<> builder(blockAllocation, blockAllocation->getFirstInsertionPt());
+
+ flagSaturation = builder.CreateAlloca(tyInt1, constTrue, "flagSaturation");
+ builder.CreateStore(constFalse, flagSaturation, true);
+}
+
+bool
+TransformerSaturation::insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx){
+ if (!flagSaturation) return false;
+
+ llvm::IRBuilder<>& builder = ctx.pass->man->llvm->builder;
+ builder.CreateCondBr(builder.CreateLoad(flagSaturation), blockExit, blockContinue);
+
+ return true;
+}
+
+} }
\ No newline at end of file
diff --git a/cpp/src/compilation/transformersaturation.h b/cpp/src/compilation/transformersaturation.h
new file mode 100644
index 0000000..b4e368a
--- /dev/null
+++ b/cpp/src/compilation/transformersaturation.h
@@ -0,0 +1,46 @@
+/*
+ * File: transformersaturation.h
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on March 25, 2017, 9:59 PM
+ */
+
+#ifndef TRANSFORMERSATURATION_H
+#define TRANSFORMERSATURATION_H
+
+#include "transformations.h"
+
+namespace xreate { namespace compilation {
+
+class TransformerSaturation: public Transformer{
+public:
+ TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager);
+ ~TransformerSaturation();
+
+ llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
+
+ void processBreak(const Context& ctx);
+
+ void allocateFlag(const Context& ctx);
+ bool insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx);
+
+private:
+ TransformationsManager* man;
+ TransformerSaturation* oldInstance = nullptr;
+
+ llvm::BasicBlock* blockAllocation;
+
+ llvm::Value* constTrue;
+ llvm::Value* constFalse;
+ llvm::Value* flagSaturation = nullptr;
+};
+
+template <>
+struct TransformerInfo<TransformerSaturation> {
+ static const unsigned int id = 0;
+};
+
+} }
+
+#endif /* TRANSFORMERSATURATION_H */
+
diff --git a/cpp/src/compilation/versions.h b/cpp/src/compilation/versions.h
new file mode 100644
index 0000000..e1f9b0d
--- /dev/null
+++ b/cpp/src/compilation/versions.h
@@ -0,0 +1,127 @@
+
+/*
+ * versions.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on January 21, 2017, 1:24 PM
+ */
+
+#include "pass/versionspass.h"
+#include "pass/compilepass.h"
+
+namespace xreate {
+
+class CompilePass;
+
+namespace compilation {
+
+class AbstractCodeScopeUnit;
+class FunctionUnit;
+
+template<class Parent>
+class VersionsScopeDecorator: public Parent{
+ typedef VersionsScopeDecorator<Parent> SELF;
+
+public:
+ VersionsScopeDecorator(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
+
+ virtual llvm::Value* processSymbol(const Symbol& s, std::string hintSymbol=""){
+ if (Attachments::exists<VersionImposedDependency>(s)){
+ const std::list<Symbol> dependencies = Attachments::get<VersionImposedDependency>(s);
+
+ for(const Symbol& symbolDependent: dependencies){
+ processSymbol(symbolDependent);
+ }
+ }
+
+ llvm::Value* result = Parent::processSymbol(s, hintSymbol);
+
+ if (s.identifier.version == VERSION_INIT){
+ llvm::Value* storage = SELF::processIntrinsicInit(result->getType(), hintSymbol);
+ setSymbolStorage(s, storage);
+
+ processIntrinsicCopy(result, storage);
+ return AbstractCodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
+
+ } else if (s.identifier.version != VERSION_NONE){
+ Symbol symbolInitVersion = getSymbolInitVersion(s);
+
+ llvm::Value* storage = getSymbolStorage(symbolInitVersion);
+ processIntrinsicCopy(result, storage);
+
+ return AbstractCodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
+ }
+
+ return result;
+ }
+
+ llvm::Value*
+ processIntrinsicInit(llvm::Type* typeStorage, const std::string& hintVarDecl=""){
+ llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::ConstantInt* constOne = llvm::ConstantInt::get(tyInt, 1, false);
+
+ return AbstractCodeScopeUnit::pass->man->llvm->builder.CreateAlloca(typeStorage, constOne, hintVarDecl);
+ }
+
+ void
+ processIntrinsicCopy(llvm::Value* value, llvm::Value* storage){
+ AbstractCodeScopeUnit::pass->man->llvm->builder.CreateStore(value, storage);
+ }
+
+private:
+ std::map<Symbol, llvm::Value*> __symbolStorage;
+
+ static Symbol
+ getSymbolInitVersion(const Symbol& s){
+ return Symbol{ScopedSymbol{s.identifier.id, VERSION_INIT}, s.scope};
+ }
+
+ llvm::Value*
+ getSymbolStorage(const Symbol& s){
+ return __symbolStorage.at(s);
+ }
+
+ void setSymbolStorage(const Symbol& s, llvm::Value* storage){
+ __symbolStorage[s] = storage;
+ }
+
+};
+} //end of compilation namespace
+} //end of xreate namespace
+
+
+// llvm::Value*
+// processIntrinsicInitAndCopy(){
+//
+// }
+
+//llvm::Value*
+//process(const Expression& expr, const std::string& hintVarDecl){
+// case Operator::CALL_INTRINSIC: {
+// enum INRINSIC{INIT, COPY};
+//
+// const ExpandedType& typSymbol = pass->man->root->expandType(expr.type);
+//
+// INTRINSIC op = (INTRINSIC) expr.getValueDouble();
+//
+// switch (op){
+// case INIT: {
+// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
+//
+//
+// return storage;
+// }
+//
+// case COPY: {
+// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
+// llvm::value* valueOriginal = process(expr.getOperands()[0], hintVarDecl);
+// llvm::Value* storage = l.builder.CreateAlloca(typSymbolRaw, constOne, hintVarDecl);
+// llvm::Value* valueCopy = l.builder.CreateStore(valueOriginal, storage);
+//
+// return valueCopy;
+// }
+// }
+// return;
+// }
+//}
+//};
\ No newline at end of file
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index fc4e19f..ca6190a 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,35 +1,58 @@
#include "abstractpass.h"
#include "attachments.h"
#include "passmanager.h"
using namespace std;
namespace xreate {
- template<>
- void defaultValue<void>(){}
+template<>
+void defaultValue<void>(){}
- void AbstractPassBase::finish(){}
+void AbstractPassBase::finish(){}
- AbstractPassBase::AbstractPassBase(PassManager *manager)
- : man(manager) {
- }
+AbstractPassBase::AbstractPassBase(PassManager *manager)
+ : man(manager) {
+}
+
+template<>
+void
+AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
+{
+ if (__visitedSymbols.isCached(symbol))
+ return;
- template<>
- void
- AbstractPass<void>::processSymbol(const std::string& ident, PassContext context)
- {
- const Symbol& symbol = context.scope->findSymbol(ident);
+ __visitedSymbols.setCachedValue(symbol);
+ const Expression& declaration = CodeScope::getDeclaration(symbol);
- if (__visitedSymbols.isCached(symbol))
- return;
+ if (declaration.isDefined()){
+ PassContext context2 = context.updateScope(symbol.scope);
+ process(declaration, context2, hintSymbol);
+ }
+}
+
+template<>
+void
+AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
+ if (expression.__state == Expression::COMPOUND){
+ for (const Expression &op: expression.getOperands()) {
+ process(op, context);
+ }
- __visitedSymbols.setCachedValue(symbol);
- const Expression& declaration = CodeScope::findDeclaration(symbol);
+ for (CodeScope* scope: expression.blocks) {
+ process(scope, context);
+ }
- if (declaration.isDefined()){
- PassContext context2 = context.updateScope(symbol.scope);
- process(declaration, context2, ident);
+ if (expression.op == Operator::CALL){
+ processExpressionCall(expression, context);
}
+
+ return;
+ }
+
+ if (expression.__state == Expression::IDENT){
+ assert(context.scope);
+ processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
}
+}
}
\ No newline at end of file
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 328a916..dfefc06 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,201 +1,194 @@
#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 updateScope(CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
- return std::move(context2);
+ return 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)[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){}
-
- virtual Output processFnCall(ManagedFnPtr function, PassContext context){
- return defaultValue<Output>();
- }
+template<class Output>
+class AbstractPass: public AbstractPassBase {
- virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context)
- {}
+ SymbolCache<Output> __visitedSymbols;
- virtual void process(ManagedRulePtr rule)
- {}
+protected:
+ virtual Output processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol=""){
+ if (__visitedSymbols.isCached(symbol))
+ return __visitedSymbols.getCachedValue(symbol);
- virtual Output process(ManagedFnPtr function)
- {
- PassContext context;
- context.function = function;
- return process(function->getEntryScope(), context);
- }
+ const Expression& declaration = CodeScope::getDeclaration(symbol);
+ if (declaration.isDefined()){
+ PassContext context2 = context.updateScope(symbol.scope);
- virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
- context.scope = scope;
- return process(scope->getBody(), context);
+ Output&& result = process(declaration, context2, hintSymbol);
+ return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
- 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>();
+ }
+
+ Output processExpressionCall(const Expression& expression, PassContext context){
+ const std::string &calleeName = expression.getValueString();
+ std::list<ManagedFnPtr> callees = man->root->getFunctionVariants(calleeName);
+ if (callees.size() == 1 && callees.front()){
+ return processFnCall(callees.front(), context);
+
+ } else {
+ for (const ManagedFnPtr& callee: callees){
+ processFnCallUncertain(callee, context);
}
return defaultValue<Output>();
}
+ }
- void run() {
- ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
- while (rule.isValid()) {
- process(rule);
- ++rule;
- }
+ SymbolCache<Output>& getSymbolCache(){
+ return __visitedSymbols;
+ }
- ManagedFnPtr f = man->root->begin<Function>();
- while (f.isValid()) {
- process(f);
- ++f;
- }
+
+
+public:
+ AbstractPass(PassManager* manager)
+ : AbstractPassBase(manager){}
+
+ 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)
+ {
+ 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 processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
+ }
+
+ virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
+ if (expression.__state == Expression::IDENT){
+ assert(context.scope);
+ return processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
}
- };
- template<>
- void
- AbstractPass<void>::processSymbol(const std::string& ident, PassContext context);
-}
+ assert(false);
+ 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 Symbol& symbol, PassContext context, const std::string& hintSymbol);
+
+template<>
+void
+AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& hintSymbol);
+
+}
#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 65cde19..35e3c50 100644
--- a/cpp/src/pass/adhocpass.cpp
+++ b/cpp/src/pass/adhocpass.cpp
@@ -1,81 +1,95 @@
/*
* 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->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);
- }
- }
+
+AdhocExpression::AdhocExpression(): Expression(Operator::ADHOC, {})
+{}
+
+AdhocExpression::AdhocExpression(const Expression& base): Expression(base)
+{}
+
+void
+AdhocExpression::setCommand(const Expression& comm){
+ this->addTags({Expression(Operator::CALL, {Atom<Identifier_t>("adhoc"), comm})});
+}
+
+Expression
+AdhocExpression::getCommand() const{
+ assert(this->tags.count("adhoc"));
+ return this->tags.at("adhoc").getOperands().at(0);
+}
+
+AdhocScheme*
+AdhocPass::findAssotiatedScheme(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 && "Can't determine relevant scheme, ambiguous context");
+ scheme = __schemes.at(context.getValueString());
+ }
+ }
+
+ assert(scheme && "Context doesn't define any ad hoc scheme");
+ return scheme;
+}
+
+const TypeAnnotation&
+AdhocScheme::getResultType(){
+ return __resultType;
+}
+
+CodeScope*
+AdhocScheme::getCommandImplementation(const Expression& comm) {
+ assert(comm.__state == Expression::IDENT);
+
+ const std::string commSerialized = comm.getValueString();
+ assert(__commands.count(commSerialized) && "Command isn't defined for a selected scheme");
+ return __commands.at(commSerialized);
+}
+
+AdhocScheme::AdhocScheme(const Expression& scheme):
+ __resultType(scheme.type), __name(scheme.getValueString()) {
+
+ Expression exprCasesList = scheme.getOperands()[0];
+ for (const Expression& exprSingleCase: exprCasesList.getOperands()){
+ std::string command = exprSingleCase.tags.begin()->second.getValueString();
+
+ CodeScope* blockImpl = *(exprSingleCase.blocks.begin());
+ __commands.emplace(command, blockImpl);
+ }
+}
+
+const std::string&
+AdhocScheme::getName(){
+ return __name;
+}
+
+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->getName(), scheme);
+ }
+}
+
}
diff --git a/cpp/src/pass/adhocpass.h b/cpp/src/pass/adhocpass.h
index 45877ad..561ebfa 100644
--- a/cpp/src/pass/adhocpass.h
+++ b/cpp/src/pass/adhocpass.h
@@ -1,50 +1,59 @@
/*
* adhoc.h
*
* Created on: Nov 28, 2015
* Author: pgess
*/
//SECTIONTAG adhoc pass
#ifndef SRC_INSTRUCTIONS_ADHOC_H_
#define SRC_INSTRUCTIONS_ADHOC_H_
#include "abstractpass.h"
-#ifndef FRIEND_ADHOC_UNITTESTS
- #define FRIEND_ADHOC_UNITTESTS
+#ifndef FRIENDS_ADHOC
+ #define FRIENDS_ADHOC
#endif
namespace xreate {
- class ContextQuery;
+class ContextQuery;
+
+class AdhocScheme {
+public:
+ AdhocScheme(const Expression& scheme);
+ CodeScope* getCommandImplementation(const Expression& comm);
+ const TypeAnnotation& getResultType();
+ const std::string& getName();
+
+private:
+ TypeAnnotation __resultType;
+ std::string __name;
+ std::map<std::string, CodeScope*> __commands;
+};
+
+class AdhocExpression: public Expression{
+public:
+ AdhocExpression();
+ AdhocExpression(const Expression& base);
+
+ void setCommand(const Expression& comm);
+ Expression getCommand() const;
+};
+
+class AdhocPass: public AbstractPass<void> {
+ FRIENDS_ADHOC
+
+public:
+ AdhocPass(PassManager* manager): AbstractPass(manager) {}
+ void run() override;
+
+ AdhocScheme* findAssotiatedScheme(CodeScope* entry);
+
+private:
+ std::map<std::string, AdhocScheme*> __schemes;
+ ContextQuery* queryContext;
+};
- class AdhocScheme {
- public:
- AdhocScheme(const Expression& scheme);
- CodeScope* getImplementationForCommand(const std::string& comm);
- const TypeAnnotation& getResultType();
- const std::string& getContext();
-
- private:
- TypeAnnotation __resultType;
- std::string __context;
- std::map<std::string, CodeScope*> __commands;
- };
-
- class AdhocPass: public AbstractPass<void> {
- FRIEND_ADHOC_UNITTESTS
-
- public:
- AdhocPass(PassManager* manager): AbstractPass(manager) {}
- AdhocScheme* determineForScope(CodeScope* entry);
-
- // virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
- void run() override;
-
- private:
- std::map<std::string, AdhocScheme*> __schemes;
- ContextQuery* queryContext;
- };
}
#endif /* SRC_INSTRUCTIONS_ADHOC_H_ */
diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp
index c4afd00..07801b6 100644
--- a/cpp/src/pass/cfapass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,100 +1,100 @@
#include "cfapass.h"
#include "analysis/cfagraph.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate;
void
CFAPass::initSignatures(){
- auto range = man->root->__interfacesData.equal_range(CFA);
- for (auto i = range.first; i!= range.second; ++i){
- __signatures.emplace(i->second.op, i->second);
- }
+ auto range = man->root->__interfacesData.equal_range(CFA);
+ for (auto i = range.first; i!= range.second; ++i){
+ __signatures.emplace(i->second.op, i->second);
+ }
}
void CFAPass::run(){
- initSignatures();
+ initSignatures();
- return AbstractPass::run();
+ return AbstractPass::run();
}
void
CFAPass::finish()
{
man->clasp->setCFAData(move(__context.graph));
return AbstractPass::finish();
}
void
CFAPass::processFnCall(ManagedFnPtr function, PassContext context)
{
- ClaspLayer* clasp = man->clasp;
- __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
+ ClaspLayer* clasp = man->clasp;
+ __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
- return AbstractPass::processFnCall(function, context);
+ return AbstractPass::processFnCall(function, context);
}
void
CFAPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){
- ClaspLayer* clasp = man->clasp;
- __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
+ ClaspLayer* clasp = man->clasp;
+ __context.graph->addCallConnection(clasp->pack(context.scope), function->getName());
- return AbstractPass::processFnCallUncertain(function, context);
+ return AbstractPass::processFnCallUncertain(function, context);
}
void
CFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
- ClaspLayer* clasp = man->clasp;
+ ClaspLayer* clasp = man->clasp;
- CodeScope* scopeParent = context.scope;
- ScopePacked scopeId = clasp->pack(scope);
+ CodeScope* scopeParent = context.scope;
+ ScopePacked scopeId = clasp->pack(scope);
- if (scopeParent){
- __context.graph->addParentConnection(scopeId, clasp->pack(scopeParent));
- } else {
- __context.graph->addParentConnection(scopeId, context.function->getName());
- }
+ if (scopeParent){
+ __context.graph->addParentConnection(scopeId, clasp->pack(scopeParent));
+ } else {
+ __context.graph->addParentConnection(scopeId, context.function->getName());
+ }
- //TOTEST scope annotations
- //SECTIONTAG context gather scope annotations
- __context.graph->addScopeAnnotations(scopeId, scope->tags);
+ //TOTEST scope annotations
+ //SECTIONTAG context gather scope annotations
+ __context.graph->addScopeAnnotations(scopeId, scope->tags);
- __context.graph->addContextRules(scopeId, scope->contextRules);
+ __context.graph->addContextRules(scopeId, scope->contextRules);
- return AbstractPass::process(scope, context, hintBlockDecl);
+ return AbstractPass::process(scope, context, hintBlockDecl);
}
//TOTEST scope annotations via scheme
void
CFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
- ClaspLayer* clasp = man->clasp;
+ ClaspLayer* clasp = man->clasp;
- if (expression.__state == Expression::COMPOUND){
- Operator op= expression.op;
+ if (expression.__state == Expression::COMPOUND){
+ Operator op= expression.op;
- if (__signatures.count(op)) {
- assert(expression.blocks.size());
+ if (__signatures.count(op)) {
+ assert(expression.blocks.size());
- for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
- __context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
- }
- }
- }
+ for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
+ __context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands());
+ }
+ }
+ }
- return AbstractPass::process(expression, context, varDecl);
+ return AbstractPass::process(expression, context, varDecl);
}
void
CFAPass::process(ManagedFnPtr function)
{
- __context.graph->addFunctionAnnotations(function->getName(), function->getTags());
- return AbstractPass::process(function);
+ __context.graph->addFunctionAnnotations(function->getName(), function->getTags());
+ return AbstractPass::process(function);
}
CFAPass::CFAPass(PassManager* manager)
- : AbstractPass(manager)
- , __context{new xreate::analysis::CFAGraph(manager->clasp)}
-{}
+ : AbstractPass(manager)
+ , __context{new xreate::analysis::CFAGraph(manager->clasp)}
+{}
\ No newline at end of file
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 78666b5..b1967c8 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,829 +1,765 @@
#include "compilepass.h"
#include "clasplayer.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 "pass/versionspass.h"
+#include "compilation/scopedecorators.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;
}
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);
+ ScopedSymbol argid{entry->__identifiers.at(arg), VERSION_NONE};
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));
+ return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
BasicFunctionDecorator::prepareBindings(){
CodeScope* entry = FunctionUnit::function->__entry;
- CodeScopeUnit* entryCompilation = FunctionUnit::getScopeUnit(entry);
+ AbstractCodeScopeUnit* entryCompilation = FunctionUnit::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = FunctionUnit::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
- VID argid = entry->__identifiers[arg];
+ ScopedSymbol argid{entry->__identifiers[arg], VERSION_NONE};
- entryCompilation->__rawVars[argid] = &*fargsI;
+ entryCompilation->bindArg(&*fargsI, argid);
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;
}
public:
LateContextCompiler2 contextCompiler;
};
//SECTIONTAG adhoc FunctionDecorator
template<class Parent>
class AdhocFunctionDecorator: public Parent{
public:
AdhocFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p) {}
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));
if (! Parent::function->isPrefunction){
return Parent::prepareResult();
}
- adhocImplementation = adhocpass->determineForScope(entry);
+ adhocImplementation = adhocpass->findAssotiatedScheme(entry);
return llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
}
public:
AdhocScheme* adhocImplementation=nullptr;
};
+//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
typedef LateContextFunctionDecorator<
AdhocFunctionDecorator<
BasicFunctionDecorator>> DefaultFunctionUnit;
-CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
- : scope(codeScope), pass(compilePass), function(f)
+AbstractCodeScopeUnit::AbstractCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
+ : pass(compilePass), function(f), scope(codeScope)
{}
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
+//DESABLEDFEATURE implement inlining
class CallStatementInline: public CallStatement{
public:
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) {
//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();
+
+ return nullptr;
}
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;
}
};
-
}
-void
-CodeScopeUnit::overrideDeclaration(const Symbol binding, Expression&& declaration){
- function->getScopeUnit(binding.scope)->__declarationsOverriden.emplace(binding.identifier, move(declaration));
+BasicCodeScopeUnit::BasicCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
+ : AbstractCodeScopeUnit(codeScope, f, compilePass)
+{}
+
+llvm::Value*
+BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar){
+ Expression declaration = CodeScope::getDeclaration(s);
+ CodeScope* scope = s.scope;
+ AbstractCodeScopeUnit* self = AbstractCodeScopeUnit::function->getScopeUnit(scope);
+
+ return self->process(declaration, hintRetVar);
}
+
//SECTIONTAG late-context find callee function
//TOTEST static late context decisions
//TOTEST dynamic late context decisions
-
CallStatement*
-CodeScopeUnit::findFunction(const std::string& calleeName){
+BasicCodeScopeUnit::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, llvm);
}
//no decisions required
if (specializations.size()==1){
if (!specializations.front()->guardContext.isValid()) {
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 = function->contextCompiler.getFunctionDemandSize();
//decision made if static context found or no late context exists(and there is default variant)
bool flagHasStaticDecision = variant || (variantDefault && !sizeDemand);
//if no late context exists
if (flagHasStaticDecision) {
FunctionUnit* calleeUnit = pass->getFunctionUnit(variant? *variant: *variantDefault);
//inlining possible based on static decision only
// if (calleeUnit->isInline()) {
// return new CallStatementInline(function, calleeUnit);
// }
return new CallStatementRaw(calleeUnit->compile(), llvm);
}
//require default variant if no static decision made
assert(variantDefault);
llvm::Function* functionVariantDefault = this->pass->getFunctionUnit(*variantDefault)->compile();
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;
-}
+//DISABLEDFEATURE transformations
+// if (pass->transformations->isAcceptable(expr)){
+// return pass->transformations->transform(expr, result, ctx);
+// }
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);
- }
-
- 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){
+BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left; llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
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();
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));
}
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"));
+ assert(false);
+ return nullptr;
+ //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.compileListAsSolidArray(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.compileMapSolidOutput(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);
- llvm::Value* aggr = compileSymbol(s, ident);
+ assert(expr.operands.size()==2);
+ assert(expr.operands[0].__state == Expression::IDENT);
+
+ const std::string& hintIdent= expr.operands[0].getValueString();
+ Symbol s = Attachments::get<Symbol>(expr.operands[0]);
+ const ExpandedType& t2 = pass->man->root->expandType(CodeScope::getDeclaration(s).type);
+
+ llvm::Value* aggr = processSymbol(s, hintIdent);
switch (t2.get().__operator)
{
case TypeOperator::STRUCT: case TypeOperator::CUSTOM:
{
- Expression idx = expr.operands.at(0);
+ const Expression& idx = expr.operands.at(1);
assert(idx.__state == Expression::STRING);
std::string idxField = idx.getValueString();
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);
- }
+ std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
+ [this] (const Expression& op){
+ return process(op);
+ }
);
- return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + ident));
+ return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
};
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: {
DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
assert(function->adhocImplementation && "Adhoc implementation not found");
- string comm = expr.operands[0].getValueString();
+ const Expression& comm = AdhocExpression(expr).getCommand();
- CodeScope* scope = function->adhocImplementation->getImplementationForCommand(comm);
- CodeScopeUnit* unitScope = function->getScopeUnit(scope);
+ CodeScope* scope = function->adhocImplementation->getCommandImplementation(comm);
+ AbstractCodeScopeUnit* unitScope = function->getScopeUnit(scope);
//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());
+ case Operator::CALL_INTRINSIC:{
+ const std::string op = expr.getValueString();
- llvm::Value* result;
- for(const Expression &op: expr.getOperands()){
- result = process(op, "");
- }
+ if (op == "copy") {
+ llvm::Value* result = process(expr.getOperands().at(0));
- return result;
+ auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
+ llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
+ decoratorVersions->processIntrinsicCopy(result, storage);
+
+ return l.builder.CreateLoad(storage, hintVarDecl);
+ }
+
+ assert(false && "undefined intrinsic");
}
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);
+ Symbol s = Attachments::get<Symbol>(expr);
+ return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER: {
+ llvm::Type* typConst;
+
+ if (expr.type.isValid()){
+ typConst = l.toLLVMType(pass->man->root->expandType(expr.type));
+
+ } else {
+ typConst = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ }
+
int literal = expr.getValueDouble();
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
+ return llvm::ConstantInt::get(typConst, 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;
-
-
+BasicCodeScopeUnit::compile(const std::string& hintBlockDecl){
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
- raw = process(scope->getBody());
- return raw;
+ Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
+ return processSymbol(symbScope);
}
-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);
-}
-
-
-
llvm::Function*
FunctionUnit::compile(){
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
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 =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*
+AbstractCodeScopeUnit*
FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
- CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
- scopes.emplace(scope, std::unique_ptr<CodeScopeUnit>(unit));
+ AbstractCodeScopeUnit* unit = new DefaultScopeUnit(scope, this, pass);
+ scopes.emplace(scope, std::unique_ptr<AbstractCodeScopeUnit>(unit));
}
return scopes.at(scope).get();
}
-CodeScopeUnit*
+AbstractCodeScopeUnit*
FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
-CodeScopeUnit*
+AbstractCodeScopeUnit*
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);
}
void
CompilePass::run(){
- transformations = new Transformations(this);
- transformations->registerTransformer(new TransformerSaturation(transformations));
-
+ managerTransformations = new TransformationsManager();
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;
- //}
-
+}
\ No newline at end of file
diff --git a/cpp/src/pass/compilepass.h b/cpp/src/pass/compilepass.h
index 416de88..2c84988 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,155 +1,167 @@
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include "abstractpass.h"
+
#include "llvm/IR/Function.h"
namespace xreate {
class AdhocScheme;
class ClaspLayer;
class ContextQuery;
class LLVMLayer;
}
//namespace llvm {
// class Function;
// class Value;
// class Type;
//}
namespace xreate {
class CompilePass;
namespace compilation {
-class CodeScopeUnit;
+class AbstractCodeScopeUnit;
class FunctionUnit;
class TargetInterpretation;
+class TransformationsManager;
struct Context{
- CodeScopeUnit* scope;
+ AbstractCodeScopeUnit* 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 {
+class AbstractCodeScopeUnit{
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="");
+ CompilePass* const pass;
+ FunctionUnit* const function;
+ CodeScope* const scope;
- CodeScope* scope;
+ AbstractCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
+ ~AbstractCodeScopeUnit(){}
-private:
- CompilePass* pass;
- llvm::Value* raw = nullptr;
- FunctionUnit* function;
- std::unordered_map<VID, Expression> __declarationsOverriden;
+ virtual llvm::Value* compile(const std::string& hintBlockDecl="")=0;
+ virtual llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="")=0;
+ virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="")=0;
+ virtual void bindArg(llvm::Value* value, std::string&& alias)=0;
+ virtual void bindArg(llvm::Value* value, const ScopedSymbol& s)=0;
+
+protected:
+ virtual CallStatement* findFunction(const std::string& callee)=0;
+};
+class BasicCodeScopeUnit: public AbstractCodeScopeUnit{
+public:
+ BasicCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
+ ~BasicCodeScopeUnit(){}
+
+ llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="");
+ llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="");
+ llvm::Value* compile(const std::string& hintBlockDecl="");
+
+protected:
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 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);
+ AbstractCodeScopeUnit* getEntry();
+ AbstractCodeScopeUnit* getScopeUnit(CodeScope* scope);
+ AbstractCodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
ManagedFnPtr function;
llvm::Function* raw = nullptr;
protected:
CompilePass* pass=nullptr;
private:
- std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
+ std::map<CodeScope*, std::unique_ptr<AbstractCodeScopeUnit>> 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;
+ friend class LateContextCompiler;
+ friend class LateContextCompiler2;
+ friend class compilation::BasicCodeScopeUnit;
+ friend class compilation::FunctionUnit;
public:
- compilation::Transformations* transformations;
+ compilation::TransformationsManager* managerTransformations;
+ compilation::TargetInterpretation* targetInterpretation;
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
compilation::FunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
void run() override;
llvm::Function* getEntryFunction();
static void prepareQueries(ClaspLayer* clasp);
+
+
private:
//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 7a019e1..49a957a 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,240 +1,262 @@
#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{
+namespace xreate {
-DFAPass::DFAPass(PassManager* manager)
- : AbstractPass(manager)
- , __context{new xreate::analysis::DFAGraph(manager->clasp)}
- , clasp(manager->clasp)
-{}
+ class DfaExpressionProcessor {
+ std::vector<xreate::analysis::SymbolNode> operands;
+ std::vector<SymbolPacked> blocks;
-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);
+ const Expression expression;
+ xreate::analysis::SymbolNode result;
+ DFAPass * const pass;
+ const PassContext context;
- 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));
+ public:
+ DfaExpressionProcessor(const Expression& expr, SymbolNode resInitial, DFAPass * const p, const PassContext c)
+ : expression(expr), result(resInitial), pass(p), context(c) {
- } 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));
- }
+ operands.reserve(expression.getOperands().size());
+ for (const Expression &op : expression.getOperands()) {
+ SymbolAnonymous symbOp(op.id);
- cache.blocks.reserve(expression.blocks.size());
- for (CodeScope* scope: expression.blocks) {
- cache.blocks.push_back(process(scope, context));
- }
+ operands.push_back(DfaExpressionProcessor(op, symbOp, pass, context).process());
+ }
- if (expression.__state == Expression::COMPOUND) {
- processCompoundOp(expression, context, cache, decl);
+ blocks.reserve(expression.blocks.size());
+ for (CodeScope* scope : expression.blocks) {
+ blocks.push_back(pass->process(scope, context));
+ }
+ }
- } else {
- processElementaryOp(expression, context, cache, decl);
- }
+ SymbolNode
+ process() {
+ if (expression.__state == Expression::COMPOUND) {
+ processCompoundOp();
- applyDependencies(expression, context, cache, decl);
- applyStaticAnnotations(expression, context, cache, decl);
- applySignatureAnnotations(expression, context, cache, decl);
- applyInPlaceAnnotations(expression, context, cache, decl);
+ } else {
+ processElementaryOp();
+ }
-//TODO Null ad hoc DFG implementation
-// if (expression.isNone()){
-// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
-// }
+ applySignatureAnnotations();
+ applyInPlaceAnnotations();
- //non initialized(SymbolInvalid) value
+ return result;
+ }
- return cache.result;
-}
+ private:
+ void
+ processElementaryOp() {
+ switch (expression.__state) {
+ case Expression::IDENT:
+ {
+ SymbolPacked symbFrom = pass->processSymbol(Attachments::get<Symbol>(expression), context, expression.getValueString());
+ SymbolPacked* symbTo = boost::get<SymbolPacked>(&result);
+ if (symbTo) {
+ pass->__context.graph->addConnection(*symbTo, SymbolNode(symbFrom), DFGConnection::STRONG);
-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();
+ } else {
+ result = SymbolNode(symbFrom);
+ }
- SymbolNode nodeFrom = AbstractPass::process(expression, context, identifier);
- if (SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result)){
- __context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::STRONG);
+ break;
+ }
- } else {
- // cache.result = nodeFrom;
+ default: break;
}
-
- 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;
+ void
+ processCompoundOp() {
+ switch (expression.op) {
+
+ //DEBT provide CALL processing
+ // 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 ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), VERSION_NONE};
+ //
+ // __context.graph->addConnection(clasp->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK);
+ // ++nodeActual;
+ // }
+ //
+ // //TODO add RET connection
+ // break;
+ // }
+
+ //MAP processing: apply PROTOTYPE relation
+ case Operator::MAP:
+ {
+ SymbolNode nodeFrom = operands.front();
+
+ SymbolPacked* nodeTo = boost::get<SymbolPacked>(&result);
+ assert(nodeTo);
+
+ pass->__context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::PROTOTYPE);
+ break;
+ }
+
+ default: break;
}
-
- //TODO represent RET connection
- break;
}
- //apply PROTOTYPE relation
- case Operator::MAP: {
- SymbolNode nodeFrom= cache.operands.front();
+ void
+ applySignatureAnnotations() {
+ if (pass->__signatures.count(expression.op)) {
+ const Expression &scheme = pass->__signatures.at(expression.op);
- SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
- assert(nodeFromPacked);
- SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result);
- assert(nodeTo);
- __context.graph->addConnection(*nodeTo, *nodeFromPacked, DFGConnection::PROTOTYPE);
- break;
- }
+ std::vector<SymbolNode>::iterator arg = operands.begin();
+ std::vector<Expression>::const_iterator tag = scheme.getOperands().begin();
- default: break;
- }
-}
+ //Assign scheme RET annotation
+ Expression retTag = *scheme.getOperands().begin();
+ if (retTag.__state != Expression::INVALID) {
+ pass->__context.graph->addAnnotation(result, move(retTag));
+ }
-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);
- }
+ ++tag;
+ while (tag != scheme.getOperands().end()) {
+ if (tag->__state != Expression::INVALID) {
+ pass->__context.graph->addAnnotation(*arg, Expression(*tag));
+ }
- for (SymbolNode &block: cache.blocks) {
- __context.graph->addDependencyConnection(cache.result, block);
- }
+ ++arg;
+ ++tag;
+ }
+
+ // TODO add possibility to have specific 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, ""));
+ // }
- 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
+ applyInPlaceAnnotations() {
+ // write down in-place expression tags:
+ for (pair<std::string, Expression> tag : expression.tags) {
+ pass->__context.graph->addAnnotation(result, Expression(tag.second));
+ }
+ }
+ };
-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;
+ DFAPass::DFAPass(PassManager* manager)
+ : AbstractPass(manager)
+ , __context{new xreate::analysis::DFAGraph(manager->clasp)}
+ , clasp(manager->clasp)
+ {}
- default: break;
+ SymbolPacked
+ DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) {
+ const SymbolPacked& symbRet = AbstractPass::process(scope, context, hintBlockDecl);
+ return symbRet;
}
-}
-
-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;
- }
+ SymbolPacked
+ DFAPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol) {
+ const Expression& declaration = CodeScope::getDeclaration(symbol);
+ const SymbolPacked& symbPacked = clasp->pack(symbol, hintSymbol);
+ DfaExpressionProcessor(declaration, symbPacked, this, context).process();
- //TODO represent RET connection
-// Expression retTag = *scheme.getOperands().begin();
-// if (retTag.__state != Expression::INVALID) {
-// __context.graph->addAnnotation(node, move(retTag));
-// }
+ return symbPacked;
}
-}
-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::run()
-{
- init();
- return AbstractPass::run();
-}
-void
-DFAPass::init()
-{
- for (const Expression& scheme: man->root->__dfadata)
- {
- __signatures.emplace(scheme.op, scheme);
+ void
+ DFAPass::init() {
+ for (const Expression& scheme : man->root->__dfadata) {
+ __signatures.emplace(scheme.op, scheme);
+ }
}
-}
-void DFAPass::finish()
-{
- man->clasp->setDFAData(move(__context.graph));
-}
+ void
+ DFAPass::finish() {
+ clasp->setDFAData(move(__context.graph));
+ }
template<>
-SymbolNode defaultValue(){return SymbolInvalid();};
-
+SymbolPacked defaultValue(){
+ assert(false);
}
+} //xreate namespace
+
+
+
+ //DEBT represent VersionaPass in declarative form using applyDependencies
+ // applyDependencies(expression, context, cache, decl);
+
+ //DEBT prepare static annotations and represent InterpretationPass in declarative form
+ // applyStaticAnnotations(expression, context, cache, decl);
+
+
+
+ //TODO Null ad hoc DFG implementation/None symbol
+ //DISABLEDFEATURE None value
+ // if (expression.isNone()){
+ // return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
+ // }
+
+ // non initialized(SymbolInvalid) value
+
+ //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: {
+ // SymbolNode identSymbol = clasp->pack(Attachments::get<Symbol>(expression), context.function->getName() + ":" + expression.getValueString());
+ // __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;
+ // }
+ //}
\ No newline at end of file
diff --git a/cpp/src/pass/dfapass.h b/cpp/src/pass/dfapass.h
index cc26e8c..0bc50a4 100644
--- a/cpp/src/pass/dfapass.h
+++ b/cpp/src/pass/dfapass.h
@@ -1,49 +1,39 @@
// Data Flow Graph determination pass
#ifndef DFGPASS_H
#define DFGPASS_H
#include "abstractpass.h"
#include "analysis/dfagraph.h"
namespace xreate {
class ClaspLayer;
+class DfaExpressionProcessor;
-class DFAPass : public AbstractPass<xreate::analysis::SymbolNode> {
+class DFAPass: public AbstractPass<SymbolPacked> {
+ friend class DfaExpressionProcessor;
+
public:
- xreate::analysis::SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
- xreate::analysis::SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
-
DFAPass(PassManager* manager);
+
+ SymbolPacked processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol="") override;
+ SymbolPacked process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void init();
- void run();
- void finish();
+ void run() override;
+ void finish() override;
private:
struct
{
xreate::analysis::DFAGraph* graph;
} __context;
- struct ExpressionCache{
- std::vector<xreate::analysis::SymbolNode> operands;
- std::vector<xreate::analysis::SymbolNode> blocks;
- xreate::analysis::SymbolNode result;
- };
-
std::map<Operator, Expression> __signatures; //DFA data for particular operators
ClaspLayer* clasp;
-
- void processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
- void processElementaryOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl="");
-
- void applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
- void applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
- void applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
- void applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl);
-};
};
+}; //end of xreate namespace
+
#endif
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index b4d399e..e75520f 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,406 +1,423 @@
/*
* File: interpretationpass.cpp
* Author: pgess
*
* Created on July 5, 2016, 5:21 PM
*/
#include "pass/interpretationpass.h"
-#include "compilation/transformations.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== ANY){
return unify(flagB, flags...);
}
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;
}
+bool
+InterpretationData::isDefault() const{
+ return (resolution == ANY && op == NONE);
+}
+
namespace details {
InterpretationResolution
recognizeTags(const map<std::string, Expression>& tags){
auto i = tags.find("interpretation");
if (i== tags.end()){
return ANY;
}
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;
}
return ANY;
}
}
void
recognizeTags(const Expression& e){
InterpretationData tag{details::recognizeTags(e.tags), NONE};
- Attachments::put<Expression, InterpretationData>(e, tag);
+ if (!tag.isDefault())
+ Attachments::put<InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f){
return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
- : AbstractPass(manager) {}
+ : AbstractPass(manager) {
+
+ Attachments::init<FunctionInterpretationData>();
+ Attachments::init<InterpretationData>();
+}
void InterpretationPass::run(){
ManagedFnPtr f = man->root->begin<Function>();
auto& visitedSymbols = getSymbolCache();
while (f.isValid()) {
- const Symbol& symbolFunction{0, f->getEntryScope()};
+ const Symbol& symbolFunction{ScopedSymbol::RetSymbol, 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 = ANY;
InterpretationOperator op = NONE;
switch (expression.__state){
+ case Expression::VARIANT:
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::IDENT: {
- resolution = Parent::processSymbol(expression.getValueString(), context);
+ resolution = Parent::processSymbol(Attachments::get<Symbol>(expression), context);
break;
}
case Expression::COMPOUND:
break;
- default: { resolution = INTR_ONLY; break;}
+ default: { resolution = CMPL_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
//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()};
+ const Symbol& symbCalleeFunc{ScopedSymbol::RetSymbol, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
- const Symbol& symbSelfFunc{0, context.function->getEntryScope()};
+ const Symbol& symbSelfFunc{ScopedSymbol::RetSymbol, context.function->getEntryScope()};
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);
}
//check arguments compatibility
- const FunctionInterpretationData& sig = FunctionInterpretationHelper::getSignature(callee);
+ const FunctionInterpretationData& calleeSignature = 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;
+ InterpretationResolution argExpected = calleeSignature.signature[op];
- assert(sig.signature[op] == argActual);
+ //TODO use args unification result to properly process function call
+ unify(argActual, argExpected);
}
if (FunctionInterpretationHelper::needPartialInterpretation(callee)){
op= CALL_INTERPRET_PARTIAL;
}
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})){
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));
+ Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), VERSION_NONE}, scopeBody};
+ getSymbolCache().setCachedValue(symbEl, InterpretationResolution(flagInput));
const std::string& nameAccum = expression.bindings[1];
- getSymbolCache().setCachedValue(scopeBody->findSymbol(nameAccum), InterpretationResolution(flagAccumInit));
+ Symbol symbAccum{ScopedSymbol{scopeBody->__identifiers.at(nameAccum), VERSION_NONE}, scopeBody};
+ getSymbolCache().setCachedValue(symbAccum, InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody = Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if (checkConstraints<QUERY_INTR_ONLY>({flagInput})){
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)
+ process(expression.operands[1], 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})){
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);
+
+ for (const Expression &op: expression.getOperands()) {
+ process(op, context);
+ }
+
+ for (CodeScope* scope: expression.blocks) {
+ Parent::process(scope, context);
+ }
+
break;
}
}
- InterpretationResolution resolutionExpected = Attachments::get<Expression, InterpretationData>(expression, {ANY, NONE})
- .resolution;
+ InterpretationResolution resolutionExpected =
+ Attachments::get<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){
- compilation::Transformations::subscribe<Expression, compilation::TargetInterpretation>(expression);
+ if (resolution != resolutionExpected && (op!=NONE || resolution == INTR_ONLY)){
+ Attachments::put<InterpretationData>(expression, {resolution, op});
}
return resolution;
}
InterpretationResolution
InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context){
- const Symbol& symbolFunction{0, function->getEntryScope()};
+ const Symbol symbolFunction{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& visitedSymbols = getSymbolCache();
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()};
+ const Symbol& symbSelfFunc{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& cache = getSymbolCache();
- const FunctionInterpretationData& dataIntrpr = FunctionInterpretationHelper::getSignature(function);
- InterpretationResolution resExpected = details::recognizeTags(function->getTags());
+ const FunctionInterpretationData& fnSignature = FunctionInterpretationHelper::getSignature(function);
+ InterpretationResolution fnResolutionExpected = details::recognizeTags(function->getTags());
//mark preliminary function resolution as expected
- if (resExpected != ANY){
- cache.setCachedValue(symbSelfFunc, move(resExpected));
+ if (fnResolutionExpected != ANY){
+ cache.setCachedValue(symbSelfFunc, move(fnResolutionExpected));
} 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]));
+ Symbol symbArg{ScopedSymbol{entry->__identifiers.at(arguments[argNo]), VERSION_NONE}, entry};
+ cache.setCachedValue(symbArg, InterpretationResolution(fnSignature.signature[argNo]));
}
- InterpretationResolution resActual = Parent::process(function);
- return unify(resActual, resExpected);
+ PassContext context;
+ context.function = function;
+ context.scope = entry;
+ InterpretationResolution resActual = process(CodeScope::getDeclaration(symbSelfFunc), context);
+ resActual = unify(resActual, fnResolutionExpected);
+ return cache.setCachedValue(symbSelfFunc, move(resActual));
}
const FunctionInterpretationData
FunctionInterpretationHelper::getSignature(ManagedFnPtr function){
- const Symbol& symbFunc{0, function->getEntryScope()};
-
- if (Attachments::exists<Symbol, FunctionInterpretationData>(symbFunc)){
- return Attachments::get<Symbol, FunctionInterpretationData>(symbFunc);
+ if (Attachments::exists<FunctionInterpretationData>(function)){
+ return Attachments::get<FunctionInterpretationData>(function);
}
FunctionInterpretationData&& data = recognizeSignature(function);
- Attachments::put<Symbol, FunctionInterpretationData>(symbFunc, data);
+ Attachments::put<FunctionInterpretationData>(function, 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));
+ Symbol symbArg{ScopedSymbol{entry->__identifiers.at(argName), VERSION_NONE}, entry};
+
+ const Expression& arg = CodeScope::getDeclaration(symbArg);
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;
}
}
-//if (res != INTR_ONLY){
-// argumentsActual.insert(no);
-//}
-
-
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
index 0d6ba84..a6434e6 100644
--- a/cpp/src/pass/interpretationpass.h
+++ b/cpp/src/pass/interpretationpass.h
@@ -1,78 +1,80 @@
/*
* 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{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;
+
+ bool isDefault() const;
};
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/pass/loggerpass.cpp b/cpp/src/pass/loggerpass.cpp
deleted file mode 100644
index f4471c8..0000000
--- a/cpp/src/pass/loggerpass.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * logging.cpp
- *
- * Created on: Jun 23, 2015
- * Author: pgess
- */
-
-#include <pass/loggerpass.h>
-#include "compilation/containers.h"
-#include "utils.h"
-
-using namespace std;
-using namespace llvm;
-namespace xreate {
-
-
-void LoggerPass::init(ClaspLayer* clasp){
- auto model = clasp->query(Config::get("logging.id"));
- if(!model) return;
-
- for (ClaspLayer::ModelIterator rec = model->first; rec!=model->second; ++rec){
- std::tuple<SymbolPacked> _v =ClaspLayer::parse<SymbolPacked>(rec->second);
- Symbol v = clasp->unpack(get<0>(_v));
-
- Attachments::put<Symbol, IsLogging>(v, true);
- }
-}
-
-void
-LoggerPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
- if (varDecl.size()){
- Symbol v = context.scope->findSymbol(varDecl);
- if (Attachments::get<Symbol, IsLogging>(v, false)){
- compilation::FunctionUnit* func = compiler->getFunctionUnit(context.function);
- compilation::CodeScopeUnit* scope = func->getScopeUnit(context.scope);
-
- compilation::Context compilationContext{scope, func, compiler};
- inject(v, compilationContext);
- }
- }
-
- return AbstractPass<void>::process(expression, context, varDecl);
-}
-
-void LoggerPass::inject(const Symbol& symbol, const compilation::Context& context){
- //TODO fix log injection
-
-// llvm::Value* source = context.scope->compileSymbol(symbol);
-// ExpandedType typSource = man->root->expandType(CodeScope::findDefinition(symbol).type);
-// string format = "";
-// switch (typSource->__value) {
-// case TypePrimitive::Int : case TypePrimitive::Num : case TypePrimitive::I32: case TypePrimitive::I8:
-// format = "%d\n";
-// break;
-//
-// case TypePrimitive::String:
-// format = "%s\n";
-// break;
-//
-// default:
-// assert(false && "No appropriate type for logging");
-// }
-//
-// xreate::compilation::Advanced instructions(context);
-//
-// LLVMLayer* llvm = context.pass->man->llvm;
-// llvm->builder.SetInsertPoint(llvm->builder.GetInsertBlock(), *source->use_begin());
-// llvm::Value* formatRaw = instructions.compileConstantStringAsPChar(format, "logformat");
-//
-// llvm->builder.CreateCall2(refPrintf, formatRaw, source);
-}
-
-void
-LoggerPass::initOutput(){
- LLVMLayer* llvm = man->llvm;
- refPrintf = llvm->module->getFunction("printf");
-
- if (!refPrintf) {
- PointerType* typPtrI8 = PointerType::get(IntegerType::get(llvm->module->getContext(), 8), 0);
- std::vector<Type*>argsPrintf{typPtrI8};
- FunctionType* signaturePrintf = FunctionType::get(
- /*Result=*/IntegerType::get(llvm->module->getContext(), 32),
- /*Params=*/argsPrintf,
- /*isVarArg=*/true);
-
- refPrintf = llvm::Function::Create(
- /*Type=*/signaturePrintf,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"printf", llvm->module); // (external, no body)
-
- refPrintf->setCallingConv(CallingConv::C);
- }
-}
-
-LoggerPass::LoggerPass(PassManager* manager)
- : AbstractPass<void>(manager)
-{
- initOutput();
- init(man->clasp);
-}
-
-void
-LoggerPass::initDependencies(CompilePass* pass){
- compiler = pass;
-}
-
-
-} /* namespace xreate */
diff --git a/cpp/src/pass/loggerpass.h b/cpp/src/pass/loggerpass.h
deleted file mode 100644
index 252e9c8..0000000
--- a/cpp/src/pass/loggerpass.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * logging.h
- *
- * Created on: Jun 23, 2015
- * Author: pgess
- */
-
-#ifndef SRC_LOGGING_H_
-#define SRC_LOGGING_H_
-
-#include "ast.h"
-#include <llvm/IR/Value.h>
-#include "pass/compilepass.h"
-#include "pass/abstractpass.h"
-#include "clasplayer.h"
-
-namespace xreate {
-
-class LoggerPass:public AbstractPass<void>, public IQuery {
-public:
- void inject(const Symbol& symbol, const compilation::Context& context);
- LoggerPass(PassManager* manager);
-
- virtual void init(ClaspLayer* clasp);
- void initDependencies(CompilePass* pass);
- virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
-
-private:
- CompilePass* compiler = nullptr;
- llvm::Function* refPrintf;
- void initOutput();
-};
-
-struct IsLogging{};
-
-template<>
-struct AttachmentsDict<IsLogging> {
- typedef bool Data;
- static const unsigned int key = 2;
-};
-
-} /* namespace xreate */
-
-#endif /* SRC_LOGGING_H_ */
diff --git a/cpp/src/pass/rulespass.cpp b/cpp/src/pass/rulespass.cpp
deleted file mode 100644
index a30c100..0000000
--- a/cpp/src/pass/rulespass.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "rulespass.h"
-
-using namespace xreate;
-
-RulesPass::RulesPass(PassManager* manager)
- : ASTPass(manager)
-{
- man->registerFilter(this, PassFilter::RULE);
-}
-
-void
-RulesPass::process(MetaRuleAbstract* rule, PassContext context)
-{
- rule->compile(*man->clasp);
-}
-
diff --git a/cpp/src/pass/rulespass.h b/cpp/src/pass/rulespass.h
deleted file mode 100644
index fefd760..0000000
--- a/cpp/src/pass/rulespass.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef RULESPASS_H
-#define RULESPASS_H
-#include "passmanager.h"
-
-namespace xreate {
-class RulesPass : public ASTPass
-{
-public:
- void process(MetaRuleAbstract* rule, PassContext context);
- RulesPass(PassManager* manager);
-}; }
-
-#endif // RULESPASS_H
diff --git a/cpp/src/pass/versionspass.cpp b/cpp/src/pass/versionspass.cpp
new file mode 100644
index 0000000..65c6853
--- /dev/null
+++ b/cpp/src/pass/versionspass.cpp
@@ -0,0 +1,377 @@
+/*
+ * versionspass.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on January 4, 2017, 3:13 PM
+ */
+
+#include <boost/optional/optional.hpp>
+
+#include "pass/versionspass.h"
+
+namespace std{
+ std::size_t
+ hash<xreate::SymbolOrPlaceholder>::operator()(xreate::SymbolOrPlaceholder const& s) const
+ {return std::hash<xreate::Symbol>()(s.symbol) + (s.flagEndOfLifePlaceholder? 9849 : 1);}
+
+ bool
+ equal_to<xreate::SymbolOrPlaceholder>::operator()(const xreate::SymbolOrPlaceholder& __x, const xreate::SymbolOrPlaceholder& __y) const
+ { return __x.flagEndOfLifePlaceholder == __y.flagEndOfLifePlaceholder && __x.symbol == __y.symbol; }
+
+ size_t
+ hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const{
+ return hash<xreate::ScopedSymbol>()(s.identifier) ^ ((long int) s.scope << 1);
+ }
+
+ bool
+ equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const{
+ return __x == __y;
+ };
+}
+
+using namespace std;
+
+namespace xreate {
+
+template<>
+std::list<Symbol>
+defaultValue<std::list<Symbol>>(){
+ return std::list<Symbol>();
+};
+
+inline std::string
+printSymbol(const SymbolOrPlaceholder& s){
+ switch(s.flagEndOfLifePlaceholder){
+ case SYMBOL: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")";
+ case PLACEHOLDER: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")+";
+ }
+
+ return "";
+}
+
+void
+VersionsGraph::__debug_print(std::ostream& output) const{
+ for(auto entry: __inferiors){
+ output << printSymbol(entry.second) << " <-" << printSymbol(entry.first) << "\n";
+ }
+}
+
+void
+VersionsGraph::defineEndOfLife(const Symbol& symbol, const Symbol& symbolSuccessor){
+ if(__dictSuccessors.count(symbol)){
+ assert("No version branches allowed yet" && false);
+ }
+
+ const SymbolOrPlaceholder& placeholder = getEndOfLife(symbol);
+
+ auto inferiorsDeferred = __inferiors.equal_range(placeholder);
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> inferiorsReassigned;
+
+ for (const auto& inf: boost::make_iterator_range(inferiorsDeferred)){
+ inferiorsReassigned.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, inf.second);
+ }
+
+ __inferiors.erase(placeholder);
+ __inferiors.insert(inferiorsReassigned.begin(), inferiorsReassigned.end());
+ __inferiors.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, SymbolOrPlaceholder{SYMBOL, symbol});
+
+ __dictSuccessors.emplace(symbol, symbolSuccessor);
+}
+
+SymbolOrPlaceholder
+VersionsGraph::getEndOfLife(const Symbol& s){
+ if (__dictSuccessors.count(s)){
+ return SymbolOrPlaceholder{SYMBOL, __dictSuccessors.at(s)}; }
+
+
+ return SymbolOrPlaceholder{PLACEHOLDER, s};
+}
+
+void
+VersionsGraph::applyNatualDependencies(const Symbol& symbol, const std::list<Symbol>& dependencies){
+ for (const Symbol& right: dependencies){
+ __inferiorsNatural.emplace(symbol, right);
+ }
+}
+
+void
+VersionsGraph::applyDependentEndOfLife(const SymbolOrPlaceholder& symbol, const list<Symbol>& dependencies){
+ for (const Symbol& right: dependencies){
+ auto rightEOF = getEndOfLife(right);
+
+ __inferiors.emplace(rightEOF, symbol);
+ }
+}
+
+bool
+VersionsGraph::tryEliminateEofAliases(const std::list<SymbolOrPlaceholder>& aliases){
+
+ if (aliases.size()==1){
+ return true;
+ }
+
+ boost::optional<Symbol> symbolActualEoF;
+ for(const SymbolOrPlaceholder alias: aliases){
+ switch(alias.flagEndOfLifePlaceholder){
+ case SYMBOL:
+ if(symbolActualEoF){
+ return false;
+ }
+
+ symbolActualEoF = alias.symbol;
+ break;
+
+ case PLACEHOLDER:
+ continue;
+ }
+ }
+
+ if(!symbolActualEoF){
+ return false;
+ }
+
+ for(const SymbolOrPlaceholder alias: aliases){
+ switch(alias.flagEndOfLifePlaceholder){
+ case SYMBOL:
+ continue;
+
+ case PLACEHOLDER:
+ defineEndOfLife(alias.symbol, symbolActualEoF.get());
+ break;
+ }
+ }
+
+ return true;
+}
+
+std::list<SymbolOrPlaceholder>
+VersionsGraph::extractCycle(const Path& path, const SymbolOrPlaceholder& symbolBeginning){
+ unsigned int posBeginning = path.at(symbolBeginning);
+
+ std::list<SymbolOrPlaceholder> result;
+
+ auto i=path.begin();
+ while(true){
+ i = std::find_if(i, path.end(), [&posBeginning](const auto& el){return el.second >=posBeginning;});
+
+ if (i!= path.end()){
+ result.push_back(i->first);
+ ++i;
+
+ } else {break; }
+ }
+
+ return result;
+}
+
+
+bool
+VersionsGraph::validateCycles(const SymbolOrPlaceholder& s,
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>& graph,
+ std::unordered_set<SymbolOrPlaceholder>& symbolsVisited,
+ Path& path)
+{
+ if (symbolsVisited.count(s)) return true;
+
+ symbolsVisited.insert(s);
+ path.emplace(s, path.size());
+
+ if (graph.count(s)){
+ //iterate over imposed dependencies
+ auto candidates = graph.equal_range(s);
+ for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
+ if (path.count(candidate->second)) {
+ std::list<SymbolOrPlaceholder> cycle = extractCycle(path, candidate->second);
+ if (!tryEliminateEofAliases(cycle)) return false;
+ continue;
+ }
+
+ if(!validateCycles(candidate->second, graph, symbolsVisited, path)) return false;
+ }
+ }
+
+ //iterate over natural dependencies
+ if (s.flagEndOfLifePlaceholder == SYMBOL) {
+ auto candidates = __inferiorsNatural.equal_range(s.symbol);
+ for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
+ if (path.count(SymbolOrPlaceholder{SYMBOL, candidate->second})){
+ return false;
+ }
+
+ if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate->second}, graph, symbolsVisited, path)) return false;
+ }
+ }
+
+ //check previous version
+ if (s.flagEndOfLifePlaceholder == PLACEHOLDER){
+ const Symbol& candidate = s.symbol;
+
+ if (path.count(SymbolOrPlaceholder{SYMBOL, candidate})){
+ std::list<SymbolOrPlaceholder> cycle = extractCycle(path, SymbolOrPlaceholder{SYMBOL, candidate});
+ if (!tryEliminateEofAliases(cycle)) return false;
+ }
+
+ if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate}, graph, symbolsVisited, path)) return false;
+ }
+
+ path.erase(s);
+ return true;
+}
+
+bool
+VersionsGraph::validateCycles(){
+ std::unordered_set<SymbolOrPlaceholder> symbolsVisited;
+ Path path;
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> graph(__inferiors);
+
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>::const_iterator s;
+ for (s = graph.begin(); s != graph.end(); ++s){
+ if(!validateCycles(s->first, graph, symbolsVisited, path)) return false;
+ }
+
+ return true;
+}
+
+bool
+VersionsGraph::validate(){
+ return validateCycles();
+}
+
+std::list<Symbol>
+VersionsGraph::expandPlaceholder(const SymbolOrPlaceholder& symbol, const Symbol& symbolPrev) const{
+ std::list<Symbol> result;
+
+ switch (symbol.flagEndOfLifePlaceholder){
+ case SYMBOL:
+ //skip self-loops
+ if (symbol.symbol == symbolPrev) return {};
+
+ return {symbol.symbol};
+
+ case PLACEHOLDER:
+ for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(symbol))){
+ list<Symbol>&& childResult = expandPlaceholder(entry.second, symbolPrev);
+ result.insert(result.end(), childResult.begin(), childResult.end());
+ }
+
+ if (__dictSuccessors.count(symbol.symbol)){
+ Symbol knownSuccessor = __dictSuccessors.at(symbol.symbol);
+
+ //skip alias loop
+ if (knownSuccessor == symbolPrev) return {};
+
+ for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(SymbolOrPlaceholder{SYMBOL, knownSuccessor}))){
+ list<Symbol>&& childResult = expandPlaceholder(entry.second, knownSuccessor);
+ result.insert(result.end(), childResult.begin(), childResult.end());
+ }
+ }
+
+ break;
+ }
+
+ return result;
+}
+
+AttachmentsContainerDefault<std::list<Symbol>>*
+VersionsGraph::representAsAttachments() const {
+ AttachmentsContainerDefault<std::list<Symbol>>* container = new AttachmentsContainerDefault<std::list<Symbol>>();
+
+ std::map<Symbol, std::list<Symbol>> containerData;
+
+ for(const auto& entry: __inferiors){
+ if(entry.first.flagEndOfLifePlaceholder == PLACEHOLDER) continue;
+
+ list<Symbol>& infs = containerData[entry.first.symbol];
+ list<Symbol>&& infsExpanded = expandPlaceholder(entry.second, entry.first.symbol);
+ infs.insert(infs.begin(), infsExpanded.begin(), infsExpanded.end());
+ }
+
+ for(const auto& entry: containerData){
+ container->put(entry.first, entry.second);
+ }
+
+ return container;
+}
+
+std::list<Symbol>
+VersionsPass::process(const Expression& expression, PassContext context, const std::string& hintSymbol){
+ if (expression.__state == Expression::COMPOUND){
+ std::list<Symbol> resultDependencies;
+
+ for (const Expression &op: expression.getOperands()) {
+ std::list<Symbol> deps = process(op, context);
+
+ resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
+ }
+
+ for (CodeScope* scope: expression.blocks) {
+ std::list<Symbol> deps = Parent::process(scope, context);
+
+ resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
+ }
+
+ return resultDependencies;
+ }
+
+ if (expression.__state == Expression::IDENT){
+ const Symbol symb = Attachments::get<Symbol>(expression);
+
+ return processSymbol(symb, context, expression.getValueString());
+ }
+
+ return {};
+}
+
+//TODO versions, check (declaration.isDefined()) before processing declaration
+list<Symbol>
+VersionsPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol){
+ list<Symbol> result{symbol};
+
+ if (__symbolsVisited.exists(symbol)){
+ return result;
+ }
+ enum {MODE_ALIAS, MODE_COPY } mode = MODE_ALIAS;
+
+ const Expression& declaration = CodeScope::getDeclaration(symbol);
+
+ if (declaration.op == Operator::CALL_INTRINSIC){
+ if (declaration.getValueString() == "copy"){
+ mode = MODE_COPY;
+ }
+ }
+
+ if (symbol.identifier.version != VERSION_NONE){
+ mode = MODE_COPY;
+
+ if (symbol.identifier.version > 0){
+ Symbol versionPrev = Symbol{ScopedSymbol{symbol.identifier.id, symbol.identifier.version-1}, symbol.scope};
+ __graph.defineEndOfLife(versionPrev, symbol);
+ }
+ }
+
+ PassContext context2 = context.updateScope(symbol.scope);
+ std::list<Symbol> dependencies = process(declaration, context2, hintSymbol);
+
+ switch (mode) {
+ case MODE_COPY: __graph.applyDependentEndOfLife(SymbolOrPlaceholder{SYMBOL, symbol}, dependencies); break;
+ case MODE_ALIAS: __graph.applyDependentEndOfLife(__graph.getEndOfLife(symbol), dependencies); break;
+ }
+
+ __graph.applyNatualDependencies(symbol, dependencies);
+ __symbolsVisited.put(symbol, true);
+ return list<Symbol>{symbol};
+}
+
+VersionsGraph&
+VersionsPass::getResultGraph(){
+ return __graph;
+}
+
+void
+VersionsPass::finish(){
+ assert(__graph.validate() && "Can't validate versions graph");
+
+ Attachments::init<VersionImposedDependency>(__graph.representAsAttachments());
+}
+
+}
\ No newline at end of file
diff --git a/cpp/src/pass/versionspass.h b/cpp/src/pass/versionspass.h
new file mode 100644
index 0000000..e13c62b
--- /dev/null
+++ b/cpp/src/pass/versionspass.h
@@ -0,0 +1,115 @@
+/*
+ * File: versionspass.h
+ * Author: v.melnychenko@xreate.org
+ *
+ * Created on January 4, 2017, 3:09 PM
+ */
+
+#ifndef VERSIONSPASS_H
+#define VERSIONSPASS_H
+
+#include "pass/abstractpass.h"
+#include <list>
+#include <functional>
+
+namespace xreate {
+
+ enum PlaceholderFlag {SYMBOL, PLACEHOLDER};
+
+ struct SymbolOrPlaceholder {
+ PlaceholderFlag flagEndOfLifePlaceholder;
+ Symbol symbol;
+ };
+
+
+} namespace std {
+
+ template<>
+ struct hash<xreate::SymbolOrPlaceholder>{
+ std::size_t operator()(xreate::SymbolOrPlaceholder const& s) const;
+ };
+
+ template<>
+ struct equal_to<xreate::SymbolOrPlaceholder>{
+ bool operator()(const xreate::SymbolOrPlaceholder& __x, const xreate::SymbolOrPlaceholder& __y) const;
+ };
+
+ template<>
+ struct hash<xreate::Symbol>{
+ size_t operator()(xreate::Symbol const& s) const;
+ };
+
+ template<>
+ struct equal_to<xreate::Symbol>{
+ bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
+ };
+
+} namespace xreate {
+
+struct VersionImposedDependency{};
+
+template<>
+struct AttachmentsDict<VersionImposedDependency>
+{
+ typedef std::list<Symbol> Data;
+ static const unsigned int key = 8;
+};
+
+class VersionsGraph{
+ public:
+ //processing API:
+ void applyNatualDependencies(const Symbol& symbol, const std::list<Symbol>& dependencies);
+ void applyDependentEndOfLife(const SymbolOrPlaceholder& symbol, const std::list<Symbol>& dependencies);
+
+ void defineEndOfLife(const Symbol& symbol, const Symbol& symbolSuccessor);
+ SymbolOrPlaceholder getEndOfLife(const Symbol& s);
+
+ bool validate();
+
+ //examination API:
+ AttachmentsContainerDefault<std::list<Symbol>>* representAsAttachments() const;
+ void __debug_print(std::ostream& output) const;
+
+ private:
+ typedef std::unordered_map<SymbolOrPlaceholder, unsigned int> Path;
+
+ std::unordered_multimap<Symbol, Symbol> __inferiorsNatural;
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> __inferiors;
+ std::unordered_map<Symbol, Symbol> __dictSuccessors;
+
+ std::list<Symbol> expandPlaceholder(const SymbolOrPlaceholder& symbol, const Symbol& symbolPrev) const;
+ std::list<SymbolOrPlaceholder> extractCycle(const Path& path, const SymbolOrPlaceholder& symbolBeginning);
+ bool tryEliminateEofAliases(const std::list<SymbolOrPlaceholder>& aliases);
+ bool validateCycles();
+ bool validateCycles(const SymbolOrPlaceholder& s,
+ std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>& graph,
+ std::unordered_set<SymbolOrPlaceholder>& symbolsVisited,
+ Path& path);
+};
+
+template<>
+std::list<Symbol>
+defaultValue<std::list<Symbol>>();
+
+class VersionsPass: public AbstractPass<std::list<Symbol>> {
+ typedef AbstractPass<std::list<Symbol>> Parent;
+
+public:
+ VersionsPass(PassManager* manager): AbstractPass<std::list<Symbol>>(manager){}
+ std::list<Symbol> process(const Expression& expression, PassContext context, const std::string& hintSymbol="") override;
+ VersionsGraph& getResultGraph();
+ virtual void finish();
+
+protected:
+ std::list<Symbol> processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol="") override;
+
+private:
+ VersionsGraph __graph;
+
+ AttachmentsContainerDefault<bool> __symbolsVisited;
+};
+
+} //end of xreate
+
+#endif /* VERSIONSPASS_H */
+
diff --git a/cpp/src/passmanager.cpp b/cpp/src/passmanager-bare.cpp
similarity index 63%
rename from cpp/src/passmanager.cpp
rename to cpp/src/passmanager-bare.cpp
index ccc9338..48c2715 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager-bare.cpp
@@ -1,120 +1,84 @@
-#include <pass/abstractpass.h>
-#include <pass/loggerpass.h>
-#include "query/containers.h"
-#include "passmanager.h"
-#include "pass/compilepass.h"
-#include "pass/adhocpass.h"
+#include "passmanager.h"
+#include <pass/abstractpass.h>
#include "Parser.h"
-#include "pass/cfapass.h"
-#include "pass/dfapass.h"
+#include "clasplayer.h"
+
#include <list>
#include <stdio.h>
using namespace xreate;
using namespace std;
PassManager*
PassManager::prepareForCode(std::string&& code){
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
return prepareForCode(&scanner);
}
PassManager*
PassManager::prepareForCode(FILE* code){
Scanner scanner(code);
return prepareForCode(&scanner);
}
PassManager*
PassManager::prepareForCode(Scanner* code){
Parser parser(code);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
PassManager* man = new PassManager;
AST* ast = new AST(parser.root);
man->root = ast;
man->clasp = new ClaspLayer();
man->clasp->ast = man->root;
man->llvm = new LLVMLayer(man->root);
- CompilePass::prepareQueries(man->clasp);
return man;
}
void
PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
{
__passes.emplace(id, pass);
__passDependencies.emplace(parent, pass);
}
AbstractPassBase*
PassManager::getPassById(const PassId& id){
assert(__passes.count(id));
return __passes[id];
}
bool
PassManager::isPassRegistered(const PassId& id){
return __passes.count(id);
}
void
PassManager::executePasses(){
std::list<AbstractPassBase*> passes{nullptr};
while (passes.size()){
AbstractPassBase* parent = passes.front();
auto range = __passDependencies.equal_range(parent);
for (auto i=range.first; i!=range.second; ++i){
AbstractPassBase* pass = i->second;
pass->run();
pass->finish();
passes.push_back(pass);
}
passes.pop_front();
}
}
-void*
-PassManager::run()
-{
- runWithoutCompilation();
- CompilePass* compiler = new CompilePass(this);
- compiler->run();
-
- //Compiler Dependents:
- LoggerPass* logger = new LoggerPass(this);
- logger->initDependencies(compiler);
- logger->run();
-
- llvm->print();
- llvm->initJit();
- return llvm->getFunctionPointer(compiler->getEntryFunction());
-}
-
-void PassManager::runWithoutCompilation(){
- if (flagIsProcessed) return;
-
- CFAPass* passCFG = new CFAPass(this);
-
- //TODO is it really DFGPass needs CFGpass?
- this->registerPass(new DFAPass(this), PassId::DFGPass, passCFG);
- this->registerPass(passCFG, PassId::CFGPass);
- this->registerPass(new AdhocPass(this), PassId::AdhocPass);
-
- this->executePasses();
- clasp->run();
- flagIsProcessed = true;
-}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager-full.cpp b/cpp/src/passmanager-full.cpp
new file mode 100644
index 0000000..5bb70b2
--- /dev/null
+++ b/cpp/src/passmanager-full.cpp
@@ -0,0 +1,49 @@
+/*
+ * passmanager-full.cpp
+ *
+ * Author: Volodymyr Melnychenko <v.melnychenko@xreate.org>
+ * Created on January 27, 2017, 7:10 PM
+ */
+
+#include "passmanager.h"
+#include "llvmlayer.h"
+#include "pass/compilepass.h"
+#include "pass/adhocpass.h"
+#include "pass/cfapass.h"
+#include "pass/dfapass.h"
+#include "pass/interpretationpass.h"
+#include "pass/versionspass.h"
+
+using namespace xreate;
+
+void PassManager::runWithoutCompilation(){
+ if (flagIsProcessed) return;
+
+ CFAPass* passCFG = new CFAPass(this);
+
+ //TODO is it really DFGPass needs CFGpass?
+ this->registerPass(new DFAPass(this), PassId::DFGPass, passCFG);
+ this->registerPass(passCFG, PassId::CFGPass);
+ this->registerPass(new AdhocPass(this), PassId::AdhocPass);
+ this->registerPass(new InterpretationPass(this), PassId::InterpretationPass);
+ this->registerPass(new VersionsPass(this), PassId::VersionsPass);
+
+ this->executePasses();
+
+ CompilePass::prepareQueries(clasp);
+ clasp->run();
+ flagIsProcessed = true;
+}
+
+void*
+PassManager::run()
+{
+ runWithoutCompilation();
+
+ CompilePass* compiler = new CompilePass(this);
+ compiler->run();
+
+ llvm->print();
+ llvm->initJit();
+ return llvm->getFunctionPointer(compiler->getEntryFunction());
+}
\ No newline at end of file
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index cb55967..0e67ba0 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,56 +1,57 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include <string>
#include <map>
//stdio external
struct _IO_FILE;
typedef struct _IO_FILE FILE;
class Scanner;
namespace xreate {
class AbstractPassBase;
class ClaspLayer;
class LLVMLayer;
class AST;
enum class PassId {
CFGPass,
CompilePass,
DFGPass,
EnvironmentTestsPass,
LoggerPass,
AdhocPass,
RulesPass,
- InterpretationPass
+ InterpretationPass,
+ VersionsPass
};
class PassManager
{
public:
~PassManager();
void*run();
void runWithoutCompilation();
void executePasses();
void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr);
AbstractPassBase* getPassById(const PassId& id);
bool isPassRegistered(const PassId& id);
static PassManager* prepareForCode(std::string&& code);
static PassManager* prepareForCode(FILE* code);
ClaspLayer* clasp;
LLVMLayer* llvm;
AST* root;
private:
//typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
//FILTERS_STORAGE __filters;
std::map<PassId, AbstractPassBase*> __passes;
std::multimap<AbstractPassBase*, AbstractPassBase*> __passDependencies;
bool flagIsProcessed = false;
static PassManager* prepareForCode(Scanner* code);
}; }
#endif
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 8f37165..1243cff 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,164 +1,165 @@
//
// Created by pgess on 3/14/15.
//
#include <clasplayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
-
-
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
- typedef Attachments attach;
-
- if (attach::exists<Symbol, Implementation>(s))
+ if (Attachments::exists<Implementation>(s))
{
- return attach::get<Symbol, Implementation>(s);
+ return Attachments::get<Implementation>(s);
}
return Implementation::create(s);
}
+
+Query::Query(){
+ Attachments::init<Implementation>();
+}
+
void
Query::init(ClaspLayer* clasp)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//read all proto data
auto range = clasp->query(Config::get("containers.id.prototypes"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom) {
auto data = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0> (data));
Symbol prototype = clasp->unpack(get<1> (data));
prototypes[root] = prototype;
}
// fill implementation data for a data sources:
range = clasp->query(Config::get("containers.id.implementations"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto data = ClaspLayer::parse<SymbolPacked, string>(atom->second);
Symbol var = clasp->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
Implementation impl = Implementation::create(var);
- Attachments::put<Symbol, Implementation>(var, move(impl));
+ Attachments::put<Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
//fill implementation data for a cluster roots
for (const pair<Symbol, string> & root: roots)
{
Symbol prototype = prototypes[root.first];
while (prototypes.count(prototype)) {
prototype = prototypes.at(prototype);
}
- Attachments::put<Symbol, Implementation>(root.first, Implementation(Attachments::get<Symbol, Implementation>(prototype)));
+ Attachments::put<Implementation>(root.first, Implementation(Attachments::get<Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
range = clasp->query(Config::get("containers.id.clusters"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto info = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0>(info));
Symbol child = clasp->unpack(get<1>(info));
- if (!(child == root)) {
- Implementation rootImpl = Attachments::get<Symbol, Implementation>(root);
- Attachments::put<Symbol, Implementation>(child, move(rootImpl));
+ if (!(child == root) && (Attachments::exists<Implementation>(root))) {
+ Implementation rootImpl = Attachments::get<Implementation>(root);
+ Attachments::put<Implementation>(child, move(rootImpl));
}
}
flagIsDataLoaded = true;
}
//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
Implementation
Implementation::create(const Symbol &var)
{
//TODO review implementation determination strategy
- Expression varDecl = CodeScope::findDeclaration(var);
+ Expression varDecl = CodeScope::getDeclaration(var);
switch (varDecl.op)
{
case Operator::LIST_RANGE: {
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST: {
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
default: break;
};
ImplementationLinkedList ill(var);
if (ill){
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
}
Implementation
Implementation::create(const Symbol& var, const std::string& implSerialized)
{
- Expression varDecl = CodeScope::findDeclaration(var);
+ Expression varDecl = CodeScope::getDeclaration(var);
if (implSerialized == Config::get("containers.impl.solid"))
{
return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
} else if (implSerialized == Config::get("containers.impl.onthefly")) {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}};
}
assert(false && "unable to determine proper implementation for the symbol");
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source){
- const Expression& sourceExpr = CodeScope::findDeclaration(source);
+ const Expression& sourceExpr = CodeScope::getDeclaration(source);
if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))){
flagIsValid = true;
Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
assert(tagLinkedlist.operands.size() == 2);
fieldPointer = tagLinkedlist.operands.at(0).getValueString();
terminator = tagLinkedlist.operands.at(1);
}
}
ImplementationLinkedList:: operator bool () const{
return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h
index ec474d0..35db039 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,83 +1,84 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
const ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
+ Query();
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/serialization/expressionserializer.cpp
index 53d6ee5..447c7d1 100644
--- a/cpp/src/serialization/expressionserializer.cpp
+++ b/cpp/src/serialization/expressionserializer.cpp
@@ -1,316 +1,318 @@
/*
* expressionserializer.cpp
*
* Created on: Jan 4, 2016
* Author: pgess
*/
#include "serialization/expressionserializer.h"
#include <boost/utility.hpp>
+#include <boost/utility/in_place_factory.hpp>
+
#include <cmath>
using namespace std;
//using namespace boost::bimaps;
namespace xreate {
struct Index {
string name;
size_t degree; //count of parameters
unsigned char level; //level in expression tree (depth of tree layer)
bool operator< (const Index other) const{
if (name != other.name) return name < other.name;
if (degree != other.degree) return degree < other.degree;
if (name != other.name) return level < other.level;
return false;
}
};
class ExpressionSerializerPrivate {
//boost::bimap<Index, multiset_of<size_t>> __registry;
struct {
map<Index,size_t> left;
} __registry;
map<unsigned char, size_t> __range;
public:
void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){
if (!target) return;
switch (e.op){
case Operator::NONE: {
switch (e.__state) {
case Expression::NUMBER:
case Expression::STRING:
case Expression::IDENT : {
Index index;
if ((e.__state == Expression::NUMBER))
index = {std::to_string(e.getValueDouble()), 0, level};
else index = {e.getValueString(), 0, level};
if (!__registry.left.count(index)){
target = boost::none;
return;
}
size_t id = __registry.left.at(index);
size_t range = __range[level];
(*target) << make_pair(id, range);
return;
}
default: break;
}
break;
}
case Operator::CALL: {
Index index{e.getValueString(), e.operands.size(), level};
if(!__registry.left.count(index)){
target = boost::none;
return;
}
size_t id = __registry.left.at(index);
size_t range = __range[level];
(*target) << make_pair(id, range);
for (const Expression& operand: e.operands){
pack(operand, level+1, target);
}
return;
}
default: break;
}
assert(false && "Expression too complicate for serialization");
}
void registerExpression(const Expression&e, unsigned char level){
switch (e.op){
case Operator::CALL: {
Index index{e.getValueString(), e.operands.size(), level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
for (const Expression& operand: e.operands){
registerExpression(operand, level+1);
}
return;
}
case Operator::NONE: {
Index index;
switch (e.__state) {
case Expression::STRING:
case Expression::IDENT: {
index = {e.getValueString(), 0, level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
return;
}
case Expression::NUMBER: {
index = {std::to_string(e.getValueDouble()), 0, level};
if (__registry.left.insert(make_pair(index, __range[level])).second){
__range[level]++;
}
return;
}
default: break;
}
break;
}
default: break;
}
assert(false && "Expression too complicate for serialization");
}
};
ExpressionSerializer::ExpressionSerializer()
: strategy(new ExpressionSerializerPrivate()){
}
ExpressionSerializer::~ExpressionSerializer() {
delete strategy;
}
void
ExpressionSerializer::registerExpression(const Expression&e){
if (e.isValid())
strategy->registerExpression(e, 0);
}
PackedExpression
ExpressionSerializer::getId(const Expression& e){
OptionalPackedExpression result(boost::in_place());
//move(PackedExpression())
strategy->pack(e, 0, result);
assert(result);
return move(*result);
}
OptionalPackedExpression
ExpressionSerializer::getIdOptional(const Expression& e) const{
OptionalPackedExpression result(boost::in_place());
//move(PackedExpression())
strategy->pack(e, 0, result);
return result;
}
ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){}
ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector<Expression>&& expressions)
: std::vector<Expression>(move(expressions)), serializer(*this){
size_t id =0;
for (const Expression& e: expressions){
__registry.emplace(serializer.getId(e), id++);
}
}
size_t
ExpressionSerializerIntegral::size() const{
return PARENT::size();
}
size_t
ExpressionSerializerIntegral::count(const Expression& e) const {
return (getIdOptional(e)? 1: 0);
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::begin() const {
return PARENT::begin();
}
ExpressionSerializerIntegral::const_iterator
ExpressionSerializerIntegral::end() const {
return PARENT::end();
}
size_t
ExpressionSerializerIntegral::getId(const Expression& e) const{
const OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
assert(exprPacked);
return __registry.at(*exprPacked);
}
boost::optional<size_t>
ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{
const OptionalPackedExpression exprPacked = serializer.getIdOptional(e);
if (!exprPacked){
return boost::none;
}
return __registry.at(*exprPacked);
}
const Expression&
ExpressionSerializerIntegral::get(size_t id) const{
return at(id);
}
void
PackedExpression::operator<< (const std::pair<size_t, size_t>& value){
static const size_t sizeSizeT = sizeof(size_t);
const size_t& id = value.first;
const size_t& range = value.second;
int countSufficientBits = range <=1? 0 : ceil(log2(range));
if (0 < countRemainedBits && countRemainedBits < countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id >> (countSufficientBits - countRemainedBits);
countSufficientBits-=countRemainedBits;
countRemainedBits = 0;
}
if (countRemainedBits == 0) {
if (countSufficientBits == 0) return;
char* __storageNew = new char[size+sizeSizeT];
std::memcpy (__storageNew, __storage, size);
std::memset(__storageNew + size, 0, sizeSizeT);
delete[] __storage;
__storage = __storageNew;
size += sizeSizeT;
countRemainedBits = 8 * sizeSizeT;
}
if (countRemainedBits >= countSufficientBits) {
size_t* tail = reinterpret_cast<size_t*>(__storage + size- sizeSizeT);
(*tail) += id << (countRemainedBits - countSufficientBits);
countRemainedBits -= countSufficientBits;
return;
}
assert("Unreachable block");
}
#if BOOST_VERSION <= 105500
PackedExpression::PackedExpression(const PackedExpression& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
}
#endif
PackedExpression::PackedExpression(PackedExpression&& other){
__storage = other.__storage;
size = other.size;
countRemainedBits = other.countRemainedBits;
other.__storage = nullptr;
}
bool
PackedExpression::operator==(const PackedExpression& other) const{
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) == 0 ;
}
return false;
}
bool
PackedExpression::operator<(const PackedExpression& other) const{
if (size < other.size) { return true; }
if (countRemainedBits < other.countRemainedBits) return true;
if (size == other.size && countRemainedBits == other.countRemainedBits){
return std::memcmp(__storage, other.__storage, size) < 0 ;
}
return false;
}
bool
PackedExpression::operator!=(const PackedExpression& other) const{
return ! ((*this) == other);
}
PackedExpression::~PackedExpression() {
delete[] __storage;
}
//PackedExpression::PackedExpression (const PackedExpression& other)
// : size(other.size), countRemainedBits(other.countRemainedBits)
//{
// __storage = new char[size];
// std::memcpy (__storage, other.__storage, size);
//}
} /* namespace xreate */
\ No newline at end of file
diff --git a/cpp/src/serialization/expressionserializer2.cpp b/cpp/src/serialization/expressionserializer2.cpp
deleted file mode 100644
index 5c63641..0000000
--- a/cpp/src/serialization/expressionserializer2.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * ExpressionSerializer2.cpp
- *
- * Created on: 9 февр. 2016
- * Author: pgess
- */
-
-#include "expressionserializer2.h"
-
-using namespace std;
-
-namespace xreate {
-
-typedef size_t ElementId;
-struct Element{
- string name;
- unsigned char degree;
- ElementId terminal = 0;
- std::list<ElementId> childs;
-
- bool operator< (const Element& other) {
- int cmp = name.compare(other.name);
- if (cmp !=0) return (cmp < 0);
- return (degree < other.degree);
- }
-
- bool operator== (const Element& other) {
- int cmp = name.compare(other.name);
- if (cmp != 0) return false;
- return degree == other.degree;
- }
-
- Element(string nameElement, unsigned int degreeElement)
- : name(nameElement), degree(degreeElement) {}
-};
-
-const Element End{"", 0};
-
-class ExpressionSerializerStrategyB {
- vector<Element> __registry;
-
- ElementId push(const Element& e, ElementId rootId){
- typedef list<ElementId>::iterator ElementIt;
-
- list<ElementId>& elements = __registry[rootId].childs;
- list<ElementId>::iterator pos = std::__lower_bound(elements.begin(), elements.end(), e,
- [this](const ElementIt& testIt, const Element& value){return __registry[*testIt] < value;});
-
- if (!(__registry[*pos] == e)) {
- __registry.push_back(e);
- ElementId result = __registry.size()-1;
- elements.insert(pos, result);
- return result;
- }
-
- return *pos;
- }
-
- ElementId registerExpression(const Expression& e, ElementId rootId) {
- switch(e.op){
- case Operator::NONE: {
- switch (e.__state) {
- case Expression::STRING:
- case Expression::IDENT: {
- const string& name = e.getValueString();
- Element element(name, 0);
- ElementId rootId = push(element, rootId);
- return rootId;
- }
-
- default: {
- break;
- }
- }
- break;
- }
-
- case Operator::CALL: {
- const string& name = e.getValueString();
- Element element(name, e.operands.size());
- ElementId rootId = push(element, rootId);
-
- for (const Expression& op: e.operands){
- Element element(op.getValueString(), op.operands.size());
- rootId = push(element, rootId);
- }
-
- return rootId;
- }
-
- default: break;
- }
-
- assert(false && "Expression too complicate for serialization");
- }
-};
-
-} /* namespace xreate */
diff --git a/cpp/src/serialization/expressionserializer2.h b/cpp/src/serialization/expressionserializer2.h
deleted file mode 100644
index 3b29756..0000000
--- a/cpp/src/serialization/expressionserializer2.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * ExpressionSerializer2.h
- *
- * Created on: 9 февр. 2016
- * Author: pgess
- */
-
-#ifndef EXPRESSIONSERIALIZER2_H_
-#define EXPRESSIONSERIALIZER2_H_
-
-#include <ast.h>
-
-namespace xreate {
-
-class ExpressionSerializer2 {
-public:
- ExpressionSerializer2();
- virtual ~ExpressionSerializer2();
-
- void registerExpression(const Expression& e);
-};
-
-} /* namespace xreate */
-
-#endif /* EXPRESSIONSERIALIZER2_H_ */
diff --git a/cpp/src/utils.cpp b/cpp/src/utils.cpp
index 693a00e..134ea62 100644
--- a/cpp/src/utils.cpp
+++ b/cpp/src/utils.cpp
@@ -1,9 +1,24 @@
#include "utils.h"
+#include <boost/locale/encoding_utf.hpp>
using namespace xreate;
Config Config::__self = Config();
Config::Config()
: __storage{json_file{ "config/default.json" }}
{}
+
+using boost::locale::conv::utf_to_utf;
+
+std::wstring
+utf8_to_wstring(const std::string& str)
+{
+ return utf_to_utf<wchar_t>(str.c_str(), str.c_str() + str.size());
+}
+
+std::string
+wstring_to_utf8(const std::wstring& str)
+{
+ return utf_to_utf<char>(str.c_str(), str.c_str() + str.size());
+}
\ No newline at end of file
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index a2f9b28..95bb82a 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,134 +1,159 @@
#ifndef UTILS_H
#define UTILS_H
#include "jeayeson/jeayeson.hpp"
//TODO use type mark to mark dirty/mutable members
/*
template<class T>
struct DdesctructableClass<T> {
}
*/
/*
template<class OriginalType>
struct TagUpdatable{
TagUpdatable(const OriginalType& source)
: __source(source)
{}
TagUpdatable() = delete;
const OriginalType& __source;
};
struct Updatable;
template <class Tag, class OT>
struct TagsDictionary
{};
template<class OT>
struct TagsDictionary<Updatable, OT>
{
typedef TagUpdatable<OT> TagName;
};
template<class Tag, class OT>
struct awareOf
{
awareOf(OT& dest)
: __dest(dest)
{}
awareOf<Tag, OT>&
operator= (const typename TagsDictionary<Tag, OT>::TagName& source)
{
__dest = source.__source;
}
private:
OT& __dest;
};
template<class Tag<OT>>
const OT&
awareOf(const Tag<OT>& holder)
{
return std::forward<OT>(holder.__source);
}
*/
namespace xreate {
template<class Tag, class Source>
struct AddTag {
explicit
AddTag(const Source &src)
: __src(src) { }
explicit
AddTag(Source &&src)
: __src(std::move(src)) { }
operator const Source&() const{
return __src;
}
const Source& get() const{
return __src;
}
const Source*
operator->() const {
return &__src;
}
private:
Source __src;
};
struct Expand_t{};
template<class Source>
using Expanded = AddTag<Expand_t, Source>;
//DEBT move to resources compiler. https://github.com/markusfisch/cpprc
class Config {
private:
json_map __storage;
static Config __self;
Config();
public:
static std::string get(std::string key) {
return __self.__storage.get_for_path<json_value>(key).get<std::string>();
}
};
+
+ /**
+ * Decorators support
+ */
+ template<class DecoratorTag>
+ struct DecoratorsDict{
+ //typedef ConcreteDecoratorForTag result;
+ };
+
+ template<class DecoratorTag>
+ struct Decorators{
+ typedef typename DecoratorsDict<DecoratorTag>::result Instance;
+
+ template<class Base>
+ static Instance* getInterface(Base* obj){
+ return dynamic_cast< Instance* > (obj);
+ }
+ };
}
+std::wstring
+utf8_to_wstring(const std::string& str);
+
+std::string
+wstring_to_utf8(const std::wstring& str);
+
+
#define RST "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
#define FRED(x) KRED << x << RST
#define FGRN(x) KGRN <<x << RST
#define FYEL(x) KYEL << x << RST
#define FBLU(x) KBLU << x << RST
#define FMAG(x) KMAG x RST
#define FCYN(x) KCYN x RST
#define FWHT(x) KWHT x RST
#define BOLD(x) "\x1B[1m" x RST
#define UNDL(x) "\x1B[4m" x RST
#endif // UTILS_H
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 25f9a64..ac038d2 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,25 +1,50 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate-tests)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES($<TARGET_PROPERTY:xreate,INCLUDE_DIRECTORIES>)
# TESTS
#=========================
FIND_PACKAGE (LLVM REQUIRED)
message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
-aux_source_directory(. TEST_FILES)
+#aux_source_directory(. TEST_FILES)
+set(TEST_FILES
+ main.cpp
+ adhoc.cpp
+ attachments.cpp
+ ast.cpp
+ cfa.cpp
+ dfa.cpp
+ compilation.cpp
+ ExpressionSerializer.cpp
+ externc.cpp
+ context.cpp
+ types.cpp
+ vendorAPI/clangAPI.cpp
+ vendorAPI/xml2.cpp
+ vendorAPI/json.cpp
+
+ containers.cpp
+ context.cpp
+ interpretation.cpp
+ loops.cpp
+
+ #supplemental/versions-algorithm-data_dependency.cpp
+ effects-versions.cpp
+)
+
add_executable(${PROJECT_NAME} ${TEST_FILES})
target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/cpp/tests/adhoc.cpp b/cpp/tests/adhoc.cpp
index eb9bafb..55b586e 100644
--- a/cpp/tests/adhoc.cpp
+++ b/cpp/tests/adhoc.cpp
@@ -1,160 +1,196 @@
/*
* 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;
+#define FRIENDS_ADHOC \
+ 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()->getBody();
- ASSERT_EQ(Operator::ADHOC, subject.op);
- ASSERT_EQ(1, subject.getOperands().size());
-
- Expression exception = subject.getOperands()[0];
- ASSERT_EQ("Exception", exception.getValueString());
+ PassManager* man = PassManager::prepareForCode (
+ "test = function:: int {\n"
+ " ad hoc exception(nonImplemented)\n"
+ "}");
+
+ Expression subject = man->root->findFunction("test")->getEntryScope()->getBody();
+ ASSERT_EQ(Operator::ADHOC, subject.op);
+
+ Expression exception = AdhocExpression(subject).getCommand();
+ 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);
+ 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());
+ 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->getName());
}
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);
+ PassManager* man = PassManager::prepareForCode (
+ " import raw (\"core/control-context.lp\")\n"
+
+ " interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case (error) {false}\n"
+ " case (success) {true}\n"
+ " }\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_2){
+ PassManager* man = PassManager::prepareForCode (
+ " import raw (\"core/control-context.lp\")\n"
+
+ " interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case (error) {false}\n"
+ " case (success) {true}\n"
+ " }\n"
+
+ " pre function expectErrors:: bool {\n"
+ " case (error) {true}\n"
+ " case (success) {false}\n"
+ " }\n"
+
+ " }\n"
+
+ " test1 = pre function {\n"
+ " context:: expectNoErrors."
+ " ad hoc success\n"
+ " }\n"
+
+ " test2 = pre function {\n"
+ " context:: expectErrors."
+ " ad hoc success\n"
+ " }"
+
+ "main = function::bool;entry {\n"
+ " test1() != test2()\n"
+ "}");
+
+ bool (*main)() = (bool (*)()) man->run();
+ bool result = main();
+ ASSERT_EQ(true, result);
}
+//TODO adhoc type. FDecl sets wrong type in prefunc case(invalid type))
TEST(Adhoc, full_contextExpectNoErrrors){
- PassManager* man = PassManager::prepareForCode (
- "import raw (\"core/control-context.lp\")\n"
-
- "interface(extern-c){\n"
- " xml2 = library:: pkgconfig(\"libxml-2.0\").\n"
- " \n"
- " include {\n"
- " xml2 = [\"stdlib.h\"]\n"
- " }.\n"
- "}"
-
- "interface(adhoc){\n"
- " pre function expectNoErrors:: bool {\n"
- " case Error {0}\n"
- " case Success {1}\n"
- " }\n"
- "}\n"
-
- "expectErrorCode = pre function(x::int){\n"
- " if (x==0)::bool {ad hoc \"Success\"}\n"
- " else {ad hoc \"Error\"}\n"
- "}\n"
-
- "main = function::bool; entry {\n"
- " context:: expectNoErrors."
- " expectErrorCode(system(\"ls -la\"))\n"
- "}" );
-
- int (*main)() = (int (*)()) man->run();
- ASSERT_EQ(1, main());
+ PassManager* man = PassManager::prepareForCode (
+ "import raw (\"core/control-context.lp\")\n"
+
+ "interface(extern-c){\n"
+ " xml2 = library:: pkgconfig(\"libxml-2.0\").\n"
+ " \n"
+ " include {\n"
+ " xml2 = [\"stdlib.h\"]\n"
+ " }.\n"
+ "}"
+
+ "interface(adhoc){\n"
+ " pre function expectNoErrors:: bool {\n"
+ " case (error) {false}\n"
+ " case (success) {true}\n"
+ " }\n"
+ "}\n"
+
+ "expectErrorCode = pre function(x::int){\n"
+ " if (x==0)::undef {ad hoc success}\n"
+ " else {ad hoc error}\n"
+ "}\n"
+
+ "main = function::bool; entry {\n"
+ " context:: expectNoErrors."
+ " expectErrorCode(system(\"ls -la\"))\n"
+ "}" );
+
+ int (*main)() = (int (*)()) man->run();
+ ASSERT_EQ(1, main());
}
+//DEBT Implement compilation of switch adhoc
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()->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());
+ PassManager* man = PassManager::prepareForCode (
+ "test1 = function:: bool {\n"
+ " x = 0. \n"
+ " switch ad hoc (x:: errors)\n"
+ " case (error) {0}\n"
+ " case (success) {1}\n"
+ "\n"
+ "}"
+ );
+
+ 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 46c637d..144a1f6 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,48 +1,68 @@
/*
* 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");
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, syntax_recognizeIdentifiers){
+ PassManager* man = PassManager::prepareForCode(R"Code(
+ test= function(a:: num):: num; entry {
+ a = b:: int.
+ b = 8:: int.
+
+ a
+ }
+ )Code");
+}
+
+TEST(AST, syntax_operatorIndex){
+ PassManager* man = PassManager::prepareForCode(R"Code(
+ test= function(a:: num):: num; entry {
+ b = a[1].
+ b
+ }
+ )Code");
+}
+
TEST(AST, DISABLED_InterfacesDataDFA){
}
TEST(AST, DISABLED_InterfacesDataExtern){
}
//TODO xreate.atg: replace all Type<> as ExprAnnotations<>
diff --git a/cpp/tests/attachments.cpp b/cpp/tests/attachments.cpp
new file mode 100644
index 0000000..54b8bba
--- /dev/null
+++ b/cpp/tests/attachments.cpp
@@ -0,0 +1,26 @@
+/*
+ * attachments.cpp
+ *
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on January 22, 2017, 12:16 PM
+ */
+
+
+
+#include "attachments.h"
+#include "ast.h"
+
+#include "gtest/gtest.h"
+
+using namespace xreate;
+
+TEST(Attachments, basic1){
+ AttachmentsContainerDefault<bool>* c = new AttachmentsContainerDefault<bool>();
+
+ Expression expTest(Atom<Number_t>(10));
+ c->put<Expression>(expTest, true);
+
+ Expression expTest2(Atom<Number_t>(11));
+
+ ASSERT_FALSE(c->exists<Expression>(expTest2));
+}
\ No newline at end of file
diff --git a/cpp/tests/basic.cpp b/cpp/tests/basic.cpp
deleted file mode 100644
index 0deb63b..0000000
--- a/cpp/tests/basic.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#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)} \
- "));
-
- 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 f01028c..42f7c4f 100644
--- a/cpp/tests/cfa.cpp
+++ b/cpp/tests/cfa.cpp
@@ -1,119 +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(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(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();
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();
+ const Expression& exprSum = scopeEntry->getDeclaration(scopeEntry->getSymbol("sum"));
+ CodeScope* scopeExpected = exprSum.blocks.front();
ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected);
ASSERT_EQ(scopeIdExpected, scopeIdActual);
}
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 e5371df..95b96b6 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,80 +1,37 @@
#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){
}
-TEST(Compilation, Sequence1){
- PassManager* man = PassManager::prepareForCode(
- "interface(extern-c){\n"
- " libFake = library:: pkgconfig(\"libxml-2.0\").\n"
- " \n"
- " include {\n"
- " libFake = [\"stdio.h\", \"stdlib.h\"]\n"
- " }.\n"
- "}"
-
- "main = function:: int; entry {\n"
- " sequence ["
- " printf(\"FIRST-\"),\n"
- " printf(\">SECOND\")\n"
- " ]"
- "}"
- );
-
- int (*main)() = (int (*)()) man->run();
-
- testing::internal::CaptureStdout();
- main();
- std::string output = testing::internal::GetCapturedStdout();
-
- ASSERT_STREQ("FIRST->SECOND", output.c_str());
-}
-
-TEST(Compilation, 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"
- "}"
+TEST(Compilation, functionEntry1){
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(
+ "func1 = function(a:: int):: int {a+8} \
+ func2 = function::int; entry {12 + func1(4)} \
+ "));
- "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"
- "]"
- "}"
- );
+ void* entryPtr = program->run();
+ int (*entry)() = (int (*)())(intptr_t)entryPtr;
- int (*main)() = (int (*)()) man->run();
- main();
+ int answer = entry();
+ ASSERT_EQ(24, answer);
}
-
TEST(Compilation, full_IFStatementWithVariantType){
PassManager* man = PassManager::prepareForCode(
- "COLORS = type variant (RED, BLUE, GREEN).\n"
+ "Color = 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"
+ " main = function(x::int):: bool; entry {\n"
+ " color = if (x == 0 )::Color {RED} else {BLUE}.\n"
+ " if (color == BLUE)::bool {true} else {false}\n"
" }"
);
- int (*main)(int) = (int (*)(int)) man->run();
- ASSERT_EQ(0, main(0));
- ASSERT_EQ(1, main(1));
+ bool (*main)(int) = (bool (*)(int)) man->run();
+ ASSERT_FALSE(main(0));
+ ASSERT_TRUE(main(1));
}
-
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 9d044d5..a9f3c2b 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,96 +1,109 @@
/*
* containers.cpp
*
* Created on: Jun 9, 2015
- * Author: pgess
+ * 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, ListAsArray){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function(x:: int):: int;entry {
a = [1, 2, 3]:: [int].
a[x]
}
)Code" );
void* mainPtr = man->run();
int (*main)(int) = (int (*)(int))mainPtr;
ASSERT_EQ(2, main(1));
delete man;
}
TEST(Containers, ListAsArray2){
PassManager* man = PassManager::prepareForCode(
R"Code(
+ // 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)).
+ }
+
+ import raw("core/containers.lp")
+
main = function:: int;entry {
+
+
a= [1, 2, 3]:: [int].
b= loop map(a->el:: int):: [int]{
2 * el
}.
sum = loop fold(b->el:: int, 0->acc):: int {
acc + el
}.
sum
}
)Code" );
void* mainPtr = man->run();
int (*main)() = (int (*)())mainPtr;
- ASSERT_EQ(0, main());
+ ASSERT_EQ(12, main());
delete man;
}
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");
+ const Symbol symb_chilrenRaw{body->getSymbol("childrenRaw"), body};
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(17, answer);
fclose(input);
}
diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp
index 847dab1..796fee1 100644
--- a/cpp/tests/context.cpp
+++ b/cpp/tests/context.cpp
@@ -1,495 +1,496 @@
/*
* 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"
" compute = function::int {\n"
" 0\n"
" }\n"
" computeFast = function:: int {\n"
" context:: computation(fast).\n"
" compute()\n"
" }\n"
" computePrecisely = function:: int {\n"
" context:: computation(precise). \n"
" compute()\n"
" }\n"
"test = function(cmnd:: int):: int; entry {\n"
" context:: arithmetic(iee754). \n"
" if (cmnd > 0)::int {computePrecisely()} else {computeFast()} \n"
"}\n"
);
ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
man->runWithoutCompilation();
CodeScope* scopeTestC = man->root->findFunction("compute")->getEntryScope();
const Domain& context = query->getContext(man->clasp->pack(scopeTestC));
int contextSize = context.size();
EXPECT_EQ(1, contextSize); //arithmetic(iee754)
}
TEST(Context, contextAsRequirementSuccessful1){
PassManager* man = PassManager::prepareForCode(
" import raw (\"core/control-context.lp\")\n"
" case context::safe {\n"
" funcSensitive = function::int {\n"
" 0\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: safe; test.\n"
" funcSensitive()\n"
" }\n"
);
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(0, main());
}
TEST(Context, contextAsRequirementFailed){
PassManager* man = PassManager::prepareForCode(
" import raw (\"core/control-context.lp\")\n"
" case context::safe {\n"
" funcSensitive = function::int {\n"
" 0\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: non_safe; test.\n"
" funcSensitive()\n"
" }\n"
);
ASSERT_DEATH(man->run(), "findFunction");
}
TEST(Context, ContextPropagationNested){
PassManager* man = PassManager::prepareForCode(
" import raw (\"core/control-context.lp\")\n"
" case context::safe {\n"
" square = function(x:: int) ::int {\n"
" x * x\n"
" }}\n"
" test = function:: int; entry {\n"
" context:: safe; test.\n"
" range = [1..10]:: [int]. \n"
" loop fold(range->x::int, 0->acc):: int { \n"
" acc + square(x) \n"
" } \n"
" }\n"
);
int (*main)() = (int (*)()) man->run();
ASSERT_EQ(385, main());
}
TEST(Context, ContextPropagationNestedInterfunction){
PassManager* man = PassManager::prepareForCode(
" import raw (\"core/control-context.lp\")\n"
" case context::toMillimeters {\n"
" convertConcrete = function(source:: num)::num {\n"
" 10 * source \n"
" }\n"
" }\n"
" case context::toInches {\n"
" convertConcrete = function(source:: num)::num {\n"
" 2 * source \n"
" }\n"
" }\n"
"convert= function(source:: num):: num { \n"
"convertConcrete(source) \n"
"} \n"
"test = function(source:: num):: num; entry {\n"
" context:: toMillimeters.\n"
" convert(1)\n"
"}\n" );
int (*main)(int) = (int (*)(int)) man->run();
ASSERT_EQ(10, main(1));
}
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"
+ " case (0) {\n"
" context:: toMillimeters.\n"
" convert(1)\n"
" }\n"
"\n"
- " case 1 {\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, 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"
+ " case (output(milli)) {truth}\n"
"\n"
" convert(1)\n"
" }" );
- man->clasp->addRawScript("true.");
+ man->clasp->addRawScript("truth.");
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"
+" rule context::X case (output(X)) {truth}\n"
"\n"
" switch (comm)::num \n"
-" case 0 {\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.");
+ man->clasp->addRawScript("truth.");
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"
+ " 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, loopContextExists){
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, pathDependentContext){
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 {
+ case (0) {
test_fromMilli(value, unitsOutput)
}
- case 1 {
+ case (1) {
test_fromCenti(value, unitsOutput)
}
case default {0}
}
test_fromCenti = function(value::num, output::num)::num{
context:: input(centi).
switch(output):: num
- case 0 {
+ case (0) {
toMeters(value)
}
- case 1 {
+ case (1) {
toKilo(value)
}
case default {0}
}
test_fromMilli = function(value::num, output::num)::num{
context:: input(milli).
switch(output):: num
- case 0 {
+ case (0) {
toMeters(value)
}
- case 1 {
+ case (1) {
toKilo(value)
}
case default {0}
}
toMeters = function(value::num)::num {
- rule context:: convert(X, meters) case input(X) {true}
+ rule context:: convert(X, meters) case (input(X)) {truth}
doConvert(value)
}
toKilo = function(value::num)::num {
- rule context:: convert(X, kilo) case input(X) {true}
+ rule context:: convert(X, kilo) case (input(X)) {truth}
doConvert(value)
}
doConvert = function(value::num)::num{
convert(value)
})CODE";
boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
+ man->clasp->addRawScript("truth.");
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));
}
+//TODO 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));
+}
+
diff --git a/cpp/tests/effects-versions.cpp b/cpp/tests/effects-versions.cpp
new file mode 100644
index 0000000..3ca9fb4
--- /dev/null
+++ b/cpp/tests/effects-versions.cpp
@@ -0,0 +1,276 @@
+/*
+ * Created on: Dec 16, 2016
+ * Author: pgess
+ */
+
+#include "pass/versionspass.h"
+#include "passmanager.h"
+
+#include "gtest/gtest.h"
+
+using namespace xreate;
+
+TEST(Effects, syntax_versions_1){
+ PassManager* man = PassManager::prepareForCode(R"Code(
+ test= function(a:: num):: num; entry {
+ x= b[8].
+ b = 5:: num.
+ x{1} = a:: num.
+
+ x{1} + a
+ }
+ )Code");
+}
+
+TEST(Effects, analysis_versions_1){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{0}= 3:: int.
+ x{1} = x{0} + 1.
+
+ x{1}
+ }
+ )Code");
+
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+
+ VersionsGraph graph = pass->getResultGraph();
+ ASSERT_TRUE(graph.validate());
+}
+
+TEST(Effects, analysis_versions_2){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function(a:: num):: num; entry {
+ x{0}= 3:: int.
+ b = [1, 2, x{0}].
+ x{1} = b[2].
+
+ x{1} + a
+ }
+ )Code");
+
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+
+ VersionsGraph graph = pass->getResultGraph();
+ ASSERT_TRUE(graph.validate());
+}
+
+TEST(Effects, analysis_versions_2_1_fail){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function(a:: num):: num; entry {
+ x{0}= 5:: int.
+ b = x{0}.
+ x{1} = 2.
+
+ b + x{1}
+ }
+ )Code");
+
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+
+ VersionsGraph graph = pass->getResultGraph();
+ graph.__debug_print(std::cout);
+ ASSERT_FALSE(graph.validate());
+}
+
+TEST(Effects, analysis_versions_2_2){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function(a:: num):: num; entry {
+ x{0}= 5:: int.
+ b = intrinsic copy(x{0}).
+ x{1} = 2.
+
+ b + x{1}
+ }
+ )Code");
+
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+
+ VersionsGraph graph = pass->getResultGraph();
+ graph.__debug_print(std::cout);
+ ASSERT_TRUE(graph.validate());
+}
+
+TEST(Effects, analysis_versions_3){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{0}= 3:: int.
+ a = x{0}:: int.
+ b = a :: int.
+ x{1} = b.
+
+ x{1}
+ }
+ )Code");
+
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+
+ VersionsGraph graph = pass->getResultGraph();
+ graph.__debug_print(std::cout);
+ ASSERT_TRUE(graph.validate());
+ std::cout << "========================\n";
+ graph.__debug_print(std::cout);
+ AttachmentsContainerDefault<std::list<Symbol>>* attachmentsDependency = graph.representAsAttachments();
+
+ CodeScope* scope = man->root->findFunction("test")->getEntryScope();
+ const std::list<Symbol>& dependenciesX1 = attachmentsDependency->get(Symbol{ScopedSymbol{1, 1}, scope});
+ ASSERT_EQ(3, dependenciesX1.size());
+}
+
+TEST(Effects, compilation_versions_1){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{1} = b.
+ b = a :: int.
+ a = x{0}:: int.
+ x{0}= 3:: int.
+
+ x{1}
+ }
+ )Code");
+
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::VersionsPass)){
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+ pass->finish();
+ }
+
+ int (*body)() = (int (*)())man->run();
+ int answer = body();
+
+ ASSERT_EQ(3, answer);
+}
+
+TEST(Effects, compilation_versions_versionInit1){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{0} = 3.
+
+ x{0}
+ }
+ )Code");
+
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::VersionsPass)){
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+ pass->finish();
+ }
+
+ int (*body)() = (int (*)())man->run();
+ int answer = body();
+
+ ASSERT_EQ(3, answer);
+}
+
+TEST(Effects, compilation_versions_versionNext1){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{0} = 5.
+ x{1} = x{0} - 2.
+
+ x{1}
+ }
+ )Code");
+
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::VersionsPass)){
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+ pass->finish();
+ }
+
+ int (*body)() = (int (*)())man->run();
+ int answer = body();
+
+ ASSERT_EQ(3, answer);
+}
+
+TEST(Effects, compilation_versions_IntrinsicCopy1){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ x{0} = 5.
+ b = intrinsic copy (x{0}).
+ x{1} = 2.
+
+ b - x{1}
+ }
+ )Code");
+
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::VersionsPass)){
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+ pass->finish();
+ }
+
+ int (*body)() = (int (*)())man->run();
+ int answer = body();
+
+ ASSERT_EQ(3, answer);
+}
+
+TEST(Effects, compilation_versions_varexchange){
+ PassManager* man = PassManager::prepareForCode(
+ R"Code(
+ test= function:: num; entry {
+ a{0} = 3.
+ b{0} = 5.
+ tmp = intrinsic copy (a{0}).
+ a{1} = b{0}.
+ b{1} = tmp.
+
+ b{1}
+ }
+ )Code");
+
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::VersionsPass)){
+ VersionsPass* pass = new VersionsPass(man);
+ pass->run();
+ pass->finish();
+ }
+
+ int (*body)() = (int (*)())man->run();
+ int answer = body();
+
+ ASSERT_EQ(3, answer);
+}
+
+
+
+
+
+/*
+TEST(Effects, analysis_versions_copy){
+
+}
+
+TEST(Effects, syntax_references1){
+
+}
+
+TEST(Effects, syntax_scope_versions1){
+
+}
+
+TEST(Effects, DynamicVersions_analysis){
+
+}
+ */
+
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
index 2542a4e..b8f9536 100644
--- a/cpp/tests/externc.cpp
+++ b/cpp/tests/externc.cpp
@@ -1,108 +1,106 @@
#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 = " \
interface(extern-c){ \
xml2 = library:: pkgconfig(\"libxml-2.0\"). \
\
include { \
xml2 = [\"libxml/tree.h\"] \
}. \
} \
";
Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(1, parser.root.__externdata.size());
for (const ExternEntry& lib : parser.root.__externdata) {
ASSERT_EQ("libxml-2.0", lib.package);
ASSERT_EQ(1, lib.headers.size());
ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
}
}
TEST(InterfaceExternC, testfetchPackageHeaders) {
ExternEntry entry{"libxml-2.0",
{}};
vector<string> args = ExternLayer::fetchPackageFlags(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
}
TEST(InterfaceExternC, testfetchPackageLibs) {
ExternEntry entry{"libxml-2.0",
{}};
vector<string> args = ExternLayer::fetchPackageLibs(entry);
ASSERT_EQ(1, args.size());
ASSERT_EQ("xml2", args.at(0));
}
TEST(InterfaceExternC, testLoadLib) {
std::string msgErr;
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)) {
cout << msgErr;
ASSERT_EQ("", msgErr);
}
ASSERT_TRUE(true);
}
TEST(InterfaceExternC, testBSD1) {
std::string code = " \n\
interface(extern-c){ \n\
libbsd = library:: pkgconfig(\"libbsd\"). \n\
\n\
include { \n\
libbsd = [\"bsd/stdlib.h\"] \n\
}. \n\
} \n"
"main= function:: int; entry{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);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST& ast = parser.root;
CodeScope* body = ast.findFunction("test")->getEntryScope();
- Symbol symbTree = body->findSymbol("tree");
-
- const TypeAnnotation& tTree = CodeScope::findDeclaration(symbTree).type;
+ const TypeAnnotation& tTree = body->getDeclaration(body->getSymbol("tree")).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/interpretation.cpp b/cpp/tests/interpretation.cpp
index 615ad92..8d0ade4 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,340 +1,369 @@
#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 {
+ main = function::bool {
x = "a":: string.
- y = if (x=="b"):: string; interpretation(force) {
- 1
+ y = if (x=="b"):: bool; interpretation(force) {
+ true
} else {
- 0
+ false
}.
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);
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
+
+ CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
+ Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
+ InterpretationData& dataSymbolY = Attachments::get<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(x:: int):: int {
- comm= "inc":: string.
+ comm= "inc":: string; interpretation(force).
- y = if (comm == "inc") {x+1} else {x}.
- y
+ y = if (comm == "inc")::int {x+1} else {x}.
+ y
}
-)Code" );
+)Code" );
- InterpretationPass* pass;
- if (man->isPassRegistered(PassId::InterpretationPass)){
- pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
- } else {
- pass = new InterpretationPass(man);
- pass->run();
- }
+ InterpretationPass* pass = new InterpretationPass(man);
+ pass->run();
- Symbol symbolY = man->root->findFunction("main")->__entry->findSymbol("y");
- InterpretationData& dataSymbolY = Attachments::get<Symbol, InterpretationData>(symbolY);
+ CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
+ Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
+ InterpretationData& dataSymbolY = Attachments::get<InterpretationData>(symbolY);
- ASSERT_EQ(ANY, dataSymbolY.resolution);
+ ASSERT_EQ(CMPL_ONLY, dataSymbolY.resolution);
ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
}
TEST(Interpretation, Compilation_StatementIF_InterpretCondition_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function(x:: int):: int; entry {
comm= "inc":: string; interpretation(force).
- y = if (comm == "inc") {x+1} else {x}.
+ y = if (comm == "inc")::int {x+1} else {x}.
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) = (int (*)(int))man->run();
int result = main(1);
ASSERT_EQ(2, result);
}
TEST(Interpretation, Compilation_StatementFOLD_INTERPRET_INPUT_1){
PassManager* man = PassManager::prepareForCode(
R"Code(
main = function(x:: int):: int; entry {
commands = ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, x->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();
}
+ const ManagedFnPtr& funcMain = man->root->findFunction("main");
+ InterpretationData& dataBody = Attachments::get<InterpretationData>(funcMain);
+ ASSERT_EQ(FOLD_INTERPRET_INPUT, dataBody.op);
+
int (*main)(int) = (int (*)(int))man->run();
int result = main(10);
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(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);
+ Symbol symbCallEv{{0, VERSION_NONE}, exprLoop.blocks.front()};
+ InterpretationData dataCallEv = Attachments::get<InterpretationData>(symbCallEv);
ASSERT_EQ(CMPL_ONLY, dataCallEv.resolution);
ASSERT_EQ(CALL_INTERPRET_PARTIAL, dataCallEv.op);
}
-TEST(Interpretation, PartialIntr_2){
+TEST(Interpretation, Compilation_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}
+ 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();
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::InterpretationPass)){
+ 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)
+TEST(Interpretation, PartialIntr_3){
+ PassManager* man = PassManager::prepareForCode(
+R"Code(
+ Command= type variant (INC, DEC, DOUBLE).
+ evaluate= function(argument:: num, code:: Command; 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]:: [Command]; interpretation(force).
+ loop fold(commands->comm::Command, 10->operand):: int{
+ evaluate(operand, comm)
+ }
+ }
+)Code" );
+ man->runWithoutCompilation();
+ if (!man->isPassRegistered(PassId::InterpretationPass)){
+ 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)
\ No newline at end of file
diff --git a/cpp/tests/loops.cpp b/cpp/tests/loops.cpp
index efa66a5..be08250 100644
--- a/cpp/tests/loops.cpp
+++ b/cpp/tests/loops.cpp
@@ -1,59 +1,178 @@
#include "passmanager.h"
#include "gtest/gtest.h"
using namespace std;
+TEST(Loop, SimpleLoop1){
+ string code =
+R"CODE(
+ main = function:: int; entry {
+ input = [1..5]:: [int].
+
+ loop fold(input->el::int, 0->sum)::int
+ {
+ sum + el
+ }
+ }
+
+)CODE";
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+
+ int answerActual = funcMain();
+ ASSERT_EQ(15, answerActual);
+}
+
TEST(Loop, Break1){
string code =
R"CODE(
main = function:: int; entry {
- input = [0..10]:: [int].
+ input = [1..10]:: [int].
- loop fold(input->el::int, 0->a)::[int]
+ loop fold(input->el::int, 0->sum)::int
{
- if (a>=5)::int {
- 5:: int; break
+ if (sum>5)::int {
+ sum:: int; break
- } else {a+el}
+ } else {sum+el}
}
}
)CODE";
xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
int (*funcMain)() = (int (*)()) man->run();
int answerActual = funcMain();
- ASSERT_EQ(5, answerActual);
+ ASSERT_EQ(6, answerActual);
+}
+
+TEST(Loop, NestedLoopsSimple1){
+ string code =
+R"CODE(
+ main = function:: int; entry {
+ listX = [1..5]:: [int].
+ loop fold(listX->x::int, 0->acc)::int
+ {
+ listY = [1..5]:: [int].
+
+ row = loop fold(listY->y::int, 1->acc):: int {
+ acc * ( y + x)
+ }.
+
+ acc + row
+ }
+ }
+
+)CODE";
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+ int answerActual = funcMain();
+
+ ASSERT_EQ(55320, answerActual);
+}
+
+TEST(Loop, NestedLoopsBreak1){
+ string code =
+R"CODE(
+ main = function:: int; entry {
+ listX = [1..5]:: [int].
+ loop fold(listX->x::int, 0->acc)::int
+ {
+ listY = [1..5]:: [int].
+ row = loop fold(listY->y::int, 1->acc):: int {
+ res = acc * ( y + x) :: int.
+
+ if (res > 20):: int {
+ 20:: int; break
+
+ } else {
+ res
+ }
+ }.
+
+ acc + row
+ }
+ }
+
+)CODE";
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+ int answerActual = funcMain();
+
+ ASSERT_EQ(100, answerActual);
+}
+
+TEST(Loop, NestedLoopsBreak2){
+ string code =
+R"CODE(
+ main = function:: int; entry {
+ listX = [1..3]:: [int].
+ loop fold(listX->x::int, 0->acc)::int
+ {
+ listY = [1..5]:: [int].
+ row = loop fold(listY->y::int, 1->acc):: int {
+ res = acc * y :: int.
+
+ if (res > 24):: int {
+ 24:: int; break
+
+ } else {
+ res
+ }
+ }.
+
+ if (x==3)::int{
+ acc:: int; break
+
+ } else {
+ acc + row
+ }
+ }
+ }
+
+)CODE";
+
+ xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code));
+ int (*funcMain)() = (int (*)()) man->run();
+ int answerActual = funcMain();
+
+ ASSERT_EQ(48, answerActual);
}
+//TEST nested loop breaks.
+//TEST 2 breaks^ outer loop break, inner loop break
+
TEST(Loop, InfiniteLoop1){
string code =
R"Code(
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(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/main.cpp b/cpp/tests/main.cpp
index 66078a2..2385205 100644
--- a/cpp/tests/main.cpp
+++ b/cpp/tests/main.cpp
@@ -1,136 +1,15 @@
#include "utils.h"
#include <gtest/gtest.h>
using namespace std;
using namespace xreate;
int main(int argc, char **argv) {
testing::GTEST_FLAG(color) = "yes";
string testsTemplate = Config::get("tests.template");
string testsFilter = Config::get(string("tests.templates.") + testsTemplate);
testing::GTEST_FLAG(filter) = testsFilter;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
-
-//TODO adopt useful tests
-
-//void testParser_1()
-//{
-// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
-// shared_ptr<Parser> parser(new Parser(scanner.get()));
-// parser->Parse();
-// flush(cout);
-
-// AST& root = parser->root;
-// LLVMLayer l(&root);
-
-// root.compile(l);
-// root.run(l);
-//}
-
-//void testClasp2()
-//{
-// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
-// shared_ptr<Parser> parser(new Parser(scanner.get()));
-// parser->Parse();
-// flush(cout);
-
-// if (parser->errors->count)
-// {
-// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
-// exit(1);
-// }
-
-// AST& root = parser->root;
-// ClaspLayer clasp;
-
-// /*
-// FunctionTagsPass(root).run(clasp);
-// RulesPass(root).run(clasp);
-
-// CFGPass(&clasp).run();
-
-// clasp.1
-// run();
-// */
-//}
-
-//void testUnsafeCode1()
-//{
-// shared_ptr<Scanner> scanner(new Scanner(L"scripts/cases/bugs-code.xreate"));
-// shared_ptr<Parser> parser(new Parser(scanner.get()));
-// parser->Parse();
-// flush(cout);
-
-// if (parser->errors->count)
-// {
-// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
-// exit(1);
-// }
-
-// AST& root = parser->root;
-// ClaspLayer clasp;
-
-// /*
-// FunctionTagsPass(root).run(clasp);
-// RulesPass(root).run(clasp);
-
-// CFGPass(&clasp).run();
-// //clasp.addRule(":- call(X, Y), tag(Y, unsafe), not tag(X, unsafe), function(X), function(Y).");
-
-// clasp.run();
-// */
-//}
-
-//void test_DFG_1()
-//{
-// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
-// shared_ptr<Parser> parser(new Parser(scanner.get()));
-// parser->Parse();
-// flush(cout);
-
-// if (parser->errors->count)
-// {
-// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
-// exit(1);
-// }
-
-// PassManager m;
-// m.clasp = new ClaspLayer();
-
-// m.llvm = new LLVMLayer(&parser->root);
-// m.root = & parser->root;
-// m.clasp->ast = m.root;
-
-// m.registerPass(new DFAPass(&m));
-// m.run();
-
-// m.clasp->run();
-// m.root->compile(*m.llvm);
-// m.root->run(*m.llvm);
-//}
-
-//void test_Xml_1()
-//{
-// shared_ptr<Scanner> scanner(new Scanner(L"scripts/input.xreate"));
-// shared_ptr<Parser> parser(new Parser(scanner.get()));
-// parser->Parse();
-// flush(cout);
-
-// if (parser->errors->count)
-// {
-// cout << "Found " << parser->errors->count << " errors. Stop" << endl;
-// exit(1);
-// }
-
-// PassManager m;
-// m.root = & parser->root;
-// m.clasp = new ClaspLayer();
-// m.clasp->ast = m.root;
-// m.llvm = new LLVMLayer(&parser->root);
-
-// m.registerPass(new DFAPass(&m));
-// m.run();
-//}
diff --git a/cpp/tests/supplemental/versions-algorithm-data_dependency.cpp b/cpp/tests/supplemental/versions-algorithm-data_dependency.cpp
new file mode 100644
index 0000000..7a4612d
--- /dev/null
+++ b/cpp/tests/supplemental/versions-algorithm-data_dependency.cpp
@@ -0,0 +1,296 @@
+
+/*
+ * File: algorithm-data_dependency
+ * Date: Dec 23, 2016
+ * Author: pgess <v.melnychenko@xreate.org>
+ */
+
+#include <unordered_set>
+#include <unordered_map>
+#include <string>
+#include <map>
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <cstdio>
+
+
+const int V_NOVERSION = -2;
+const int V_ENDOFLIFE = -1;
+
+struct Symbol {
+ std::string name;
+ int version;
+
+ Symbol getNextVersion() const{
+ return Symbol{name, version+1};
+ }
+};
+
+namespace std
+{
+ template<>
+ struct hash<Symbol>
+ {
+ typedef Symbol argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const& s) const
+ {
+ result_type const h1 ( std::hash<std::string>()(s.name) );
+ return h1 ^ (s.version << 1); // or use boost::hash_combine
+ }
+ };
+
+ template<>
+ struct equal_to<Symbol>
+ {
+ typedef Symbol argument_type;
+
+ bool operator()(const argument_type& __x, const argument_type& __y) const
+ { return __x.name == __y.name && __x.version == __y.version; }
+ };
+}
+
+//Ограничения:
+// - точно знаем следующую версию на этапе декл. (C.NV.1)
+
+class DDSolver{
+public:
+
+ void l1_applyLowerBound(const Symbol& left, const std::initializer_list<Symbol>& dependencies){
+ for (Symbol right: dependencies){
+ //lower bound:
+ __infs.emplace(left, right);
+ __sups.emplace(right, left);
+ }
+ }
+
+ void l1_applyOwnUpperBound(const Symbol& left){
+ //own upper bound:
+ //C.NV.1
+ __infs.emplace(left.getNextVersion(), left);
+ __sups.emplace(left, left.getNextVersion());
+ }
+
+ void l1_applyDependentUpperBound(const Symbol& left, const std::initializer_list<Symbol>& dependencies){
+ // additionally apply dependent upper bound
+ for (Symbol right: dependencies){
+ auto right2 = right.getNextVersion();
+
+ __infs.emplace(right2, left);
+ __sups.emplace(left, right2);
+ }
+ }
+
+ void addVariable(const Symbol& left, const std::initializer_list<Symbol>& dependencies){
+ l1_applyLowerBound(left, dependencies);
+ l1_applyOwnUpperBound(left);
+
+ //initialization upper bound
+ l1_applyDependentUpperBound(left, dependencies);
+
+ }
+
+ //TODO assert: only aliases allowed
+ void addAlias(const Symbol& left, const std::initializer_list<Symbol>& dependencies){
+ l1_applyLowerBound(left, dependencies);
+ l1_applyOwnUpperBound(left);
+
+ //lifetime upper bound
+ l1_applyDependentUpperBound(left.getNextVersion(), dependencies);
+ }
+
+
+ bool checkCyclicComponent(const Symbol& s, std::unordered_set<Symbol>& symbolsVisited, std::unordered_set<Symbol>& symbolsSups){
+ if (symbolsVisited.count(s)) return false;
+
+ symbolsVisited.insert(s);
+ symbolsSups.insert(s);
+
+ auto rangeInf = __infs.equal_range(s);
+ if (__infs.count(s))
+ for (auto sInf = rangeInf.first; sInf != rangeInf.second; ++sInf){
+ if (symbolsSups.count(sInf->second)) {
+ __flagCycle = std::make_pair(sInf->second, s);
+ return true;
+ }
+ if(checkCyclicComponent(sInf->second, symbolsVisited, symbolsSups)) return true;
+ }
+
+ symbolsSups.erase(s);
+ return false;
+ }
+
+ bool checkCyclicFull(){
+ std::unordered_set<Symbol> symbolsVisited, symbolsSups;
+
+ std::unordered_multimap<Symbol, Symbol>::iterator s;
+ for (s = __infs.begin(); s != __infs.end(); ++s){
+ if(checkCyclicComponent(s->first, symbolsVisited, symbolsSups)) return true;
+ }
+
+ return false;
+ }
+
+ bool validate(){
+ return !checkCyclicFull();
+ }
+
+ void solve(){
+ std::unordered_set<Symbol> binEnabled, binFrontier;
+
+ //seed
+ for (auto edge: __sups){
+ if (! __infs.count(edge.first)){
+ binEnabled.insert(edge.first);
+ binFrontier.insert(edge.first);
+ }
+ }
+
+ while (binFrontier.size()){
+ const Symbol& node= *binFrontier.begin();
+
+ //print node:
+ std:: printf("put (%s, %d)\n", node.name.c_str(), node.version);
+
+ auto rangeSups = __sups.equal_range(node);
+ for(auto sup=rangeSups.first; sup != rangeSups.second; ++sup){
+ bool flagEnabled = true;
+
+ auto rangeInfs = __infs.equal_range(sup->second);
+ for (auto inf=rangeInfs.first; inf != rangeInfs.second; ++inf){
+ if (!binEnabled.count(inf->second)){
+ flagEnabled = false;
+ break;
+ }
+ }
+
+ if (flagEnabled){
+ binEnabled.insert(sup->second);
+ binFrontier.insert(sup->second);
+ }
+ }
+
+ binFrontier.erase(node);
+ }
+ }
+
+ void solve2(Symbol nodeEntry, std::unordered_set<Symbol>& binPreviousNodes, std::unordered_set<Symbol>& binEnabledNodes){
+ binPreviousNodes.insert(nodeEntry);
+
+ auto rangeChilds = __infs.equal_range(nodeEntry);
+ for(auto node=rangeChilds.first; node != rangeChilds.second; ++node){
+ if (binEnabledNodes.count(node->second)) continue;
+
+ auto nodeError = binPreviousNodes.find(node->second);
+ if (nodeError != binPreviousNodes.end()){
+ std:: printf("(%s, %d) - (%s, %d)",
+ nodeError->name.c_str(), nodeError->version,
+ node->second.name.c_str(), node->second.version);
+ assert(false);
+ }
+
+ solve2(node->second, binPreviousNodes, binEnabledNodes);
+ }
+
+ std:: printf("put (%s, %d)\n", nodeEntry.name.c_str(), nodeEntry.version);
+ binEnabledNodes.insert(nodeEntry);
+ binPreviousNodes.erase(nodeEntry);
+
+// auto rangeParents = __sups.equal_range(nodeEntry);
+// for(auto node=rangeParents.first; node != rangeParents.second; ++node){
+// std::unordered_set<Symbol> binEmpty;
+// solve2(node->second, binEmpty, binEnabledNodes);
+// }
+ }
+
+ void __debug_printGraph(){
+ for (auto edge: __infs){
+ std:: printf("(%s, %d) <- (%s, %d) \n",
+ edge.second.name.c_str(), edge.second.version,
+ edge.first.name.c_str(), edge.first.version);
+ }
+ }
+
+private:
+ std::unordered_multimap<Symbol, Symbol> __sups;
+ std::unordered_multimap<Symbol, Symbol> __infs;
+
+public:
+ std::pair<Symbol, Symbol> __flagCycle;
+};
+
+TEST(Datadependency, test1){
+ DDSolver solver;
+
+ solver.addAlias(Symbol{"c", V_NOVERSION}, {Symbol{"a", 0}});
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"b", 0}});
+ solver.addVariable(Symbol{"b", 1}, {Symbol{"c", V_NOVERSION}});
+
+ solver.__debug_printGraph();
+
+ ASSERT_FALSE(solver.validate());
+
+ std:: printf("(%s, %d) - (%s, %d)",
+ solver.__flagCycle.first.name.c_str(), solver.__flagCycle.first.version,
+ solver.__flagCycle.second.name.c_str(), solver.__flagCycle.second.version);
+}
+
+TEST(Datadependency, test2){
+ DDSolver solver;
+
+ solver.addVariable(Symbol{"c", V_NOVERSION}, {Symbol{"a", 0}});
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"b", 0}});
+ solver.addVariable(Symbol{"b", 1}, {Symbol{"c", V_NOVERSION}});
+
+ ASSERT_TRUE(solver.validate());
+
+ solver.solve();
+}
+
+TEST(Datadependency, test3){
+ DDSolver solver;
+
+ solver.addVariable(Symbol{"c", V_NOVERSION}, {Symbol{"a", 0}});
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"b", 0}});
+ solver.addVariable(Symbol{"b", 1}, {Symbol{"c", V_NOVERSION}});
+
+ std::unordered_set<Symbol> binPreviousNodes, binEnabledNodes;
+ solver.solve2(Symbol{"b", 1}, binPreviousNodes, binEnabledNodes);
+ ASSERT_TRUE(true);
+}
+
+TEST(Datadependency, test4){
+ DDSolver solver;
+
+ solver.addVariable(Symbol{"c", V_NOVERSION}, {Symbol{"a", 0}});
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"b", 0}});
+ solver.addVariable(Symbol{"b", 1}, {Symbol{"c", V_NOVERSION}});
+
+ std::unordered_set<Symbol> binPreviousNodes, binEnabledNodes;
+ solver.solve2(Symbol{"b", 1}, binPreviousNodes, binEnabledNodes);
+ ASSERT_TRUE(true);
+}
+
+TEST(Datadependency, test5){
+ DDSolver solver;
+
+ solver.addAlias(Symbol{"b", V_NOVERSION}, {Symbol{"a", 0}});
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"b", V_NOVERSION}});
+
+ std:: printf("(%s, %d) - (%s, %d)",
+ solver.__flagCycle.first.name.c_str(), solver.__flagCycle.first.version,
+ solver.__flagCycle.second.name.c_str(), solver.__flagCycle.second.version);
+
+ ASSERT_TRUE(solver.validate());
+}
+
+TEST(Datadependency, test6){
+ DDSolver solver;
+
+ solver.addVariable(Symbol{"a", 1}, {Symbol{"a", 0}});
+
+ std::unordered_set<Symbol> binPreviousNodes, binEnabledNodes;
+ solver.solve2(Symbol{"a", 1}, binPreviousNodes, binEnabledNodes);
+
+ ASSERT_TRUE(solver.validate());
+}
\ No newline at end of file
diff --git a/cpp/tests/testClangAPI.h b/cpp/tests/testClangAPI.h
deleted file mode 100644
index aab7ee5..0000000
--- a/cpp/tests/testClangAPI.h
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// Created by pgess on 4/16/15.
-//
-
-#ifndef XREATE_TESTCLANGAPI_H
-#define XREATE_TESTCLANGAPI_H
-
-void testClang1();
-#endif //XREATE_TESTCLANGAPI_H
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index d90a673..b9d3e96 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,167 +1,163 @@
/*
* 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);
+ 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 symb = body->findSymbol("childrenRaw");
-
- const TypeAnnotation& t = CodeScope::findDeclaration(symb).type;
+ const TypeAnnotation& t = body->getDeclaration(body->getSymbol("childrenRaw")).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 TypeAnnotation& t = body->getDeclaration(body->getSymbol("tree")).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()->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 {GREEN} \n"
"main = function:: int; entry { \n"
" switch(test()):: int \n"
- " case GREEN {0} \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/scripts/dsl/regexps.xreate b/scripts/dsl/regexps.xreate
deleted file mode 100644
index b02d3e1..0000000
--- a/scripts/dsl/regexps.xreate
+++ /dev/null
@@ -1,81 +0,0 @@
-===========================
- DATA
-
-patternAB = {
- sequence: [
- {zeroOrMore: 'a'},
- {text: 'b'},
- ]
-}
-
-mod sequence{
-[
- mod zeroOrMore (text("a")),
- matcher text("b")
-]
-)
-
-
-==========================
- HANDLERS
-
- case matcher:: mod sequence
-match = function(text, matcher) {
- loop fold(node-> matcher, 0->pos){
- n = match(matcher, mid(text, pos, length(text))).// <-- every time length?
-
- if (pos == pos_FAIL || n == pos_FAIL){
- pos_FAIL:: break
- } else {
- pos+n
- }
- }
-}
-
- case matcher:: mod zeroOrMore (Dereferenced)
-match= function(text, matcher){
- matcherChild = matcher:: Dereferenced. //<--- extract child(unification)
-
- loop fold inf(0->pos, n==pos_FAIL){ //<--- infinite loop?
- n = match(matcherChild, mid(text, pos, length(text))).
-
- if (n == pos_FAIL:: break){
- pos
-
- } else {
- pos+n
- }
- }
-}
-
- case matcher:: matcher text
-match = function(text, matcher) {
- pattern = matcher:: string.
-
- if (length(text)>0 &&
- length(pattern) <= length(text) &&
- mid(text, 0, length(pattern)) == pattern)
- {
- length(pattern);
-
- } else {
- pos_FAIL;
- }
-}
-
-match = function(text::string, pattern::string)::string{
- n= match(pattern, text).
-
- if (n != pos_FAIL)
- {mid(text, 0, n)}
- else
- {text_FAIL}
-}
-
-=================================
- CLIENT
-
-test = function(){
- match(patternAB, "aaaaab").
- match(patternAB, "baaaaa").
-}
diff --git a/scripts/testspass/Containers_Implementation_LinkedList1.xreate b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
index 2966ef4..8340f56 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 index:: (op(randaccess)). - BREAKS THE ANALYSIS. MAKE tree VIEWED AS COLLECTION */
/* 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 = "scripts/testspass/Containers_Implementation_LinkedList1-data.xml" :: string.
docRaw = xmlParseFile(filename) :: xmlDocPtr.
tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
- childrenRaw = tree["children"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+ childrenRaw = tree["children"]:: [xmlNodePtr]; linkedlist(next, null).
size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count):: int {
count +1::int
}.
size
}

Event Timeline