No OneTemporary

File Metadata

Created
Mon, Feb 16, 1:15 AM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/coco/Parser.cpp b/coco/Parser.cpp
deleted file mode 100644
index 9fe0289..0000000
--- a/coco/Parser.cpp
+++ /dev/null
@@ -1,859 +0,0 @@
-/*----------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported to C++ by Csaba Balazs, University of Szeged
-with improvements by Pat Terry, Rhodes University
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than
-Coco/R itself) does not fall under the GNU General Public License.
------------------------------------------------------------------------*/
-
-
-#include <wchar.h>
-#include "Parser.h"
-#include "Scanner.h"
-
-
-
-
-void Parser::SynErr(int n) {
- if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
- errDist = 0;
-}
-
-void Parser::SemErr(const wchar_t* msg) {
- if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
- errDist = 0;
-}
-
-void Parser::Get() {
- for (;;) {
- t = la;
- la = scanner->Scan();
- if (la->kind <= maxT) { ++errDist; break; }
-
- if (dummyToken != t) {
- dummyToken->kind = t->kind;
- dummyToken->pos = t->pos;
- dummyToken->col = t->col;
- dummyToken->line = t->line;
- dummyToken->next = NULL;
- coco_string_delete(dummyToken->val);
- dummyToken->val = coco_string_create(t->val);
- t = dummyToken;
- }
- la = t;
- }
-}
-
-void Parser::Expect(int n) {
- if (la->kind==n) Get(); else { SynErr(n); }
-}
-
-void Parser::ExpectWeak(int n, int follow) {
- if (la->kind == n) Get();
- else {
- SynErr(n);
- while (!StartOf(follow)) Get();
- }
-}
-
-bool Parser::WeakSeparator(int n, int syFol, int repFol) {
- if (la->kind == n) {Get(); return true;}
- else if (StartOf(repFol)) {return false;}
- else {
- SynErr(n);
- while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) {
- Get();
- }
- return StartOf(syFol);
- }
-}
-
-void Parser::Xreate() {
- while (StartOf(1)) {
- if (la->kind == _ident) {
- FDecl();
- } else if (la->kind == 37 /* "rule" */) {
- RuleDecl();
- } else if (la->kind == 29 /* "pass" */) {
- PassData();
- } else {
- Imprt();
- }
- }
-}
-
-void Parser::FDecl() {
- std::wstring fname; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut;
- Ident(fname);
- Expect(_assign);
- Expect(11 /* "function" */);
- Expect(12 /* ":" */);
- Function* f = new Function(fname); CodeScope* entry = f->getEntryScope();
- if (StartOf(2)) {
- Type(typOut);
- f->setReturnType(typOut);
- } else if (la->kind == _lparen) {
- Get();
- if (la->kind == _ident) {
- Ident(varname);
- Expect(12 /* ":" */);
- Type(typIn);
- f->addArg(std::move(varname), move(typIn));
- while (la->kind == 13 /* "," */) {
- Get();
- Ident(varname);
- Expect(12 /* ":" */);
- Type(typIn);
- f->addArg(std::move(varname), move(typIn));
- }
- }
- Expect(_rparen);
- Expect(_implic);
- Type(typOut);
- f->setReturnType(typOut);
- while (la->kind == 13 /* "," */) {
- Get();
- FnTag(f);
- }
- } else SynErr(49);
- BDecl(entry);
- root.add(f);
-}
-
-void Parser::RuleDecl() {
- Expect(37 /* "rule" */);
- Expect(12 /* ":" */);
- RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg;
- Expect(_lparen);
- Ident(arg);
- Expect(12 /* ":" */);
- Domain(typ);
- args.add(arg, typ);
- while (la->kind == 13 /* "," */) {
- Get();
- Ident(arg);
- Expect(12 /* ":" */);
- Domain(typ);
- args.add(arg, typ);
- }
- Expect(_rparen);
- if (la->kind == 38 /* "case" */) {
- Get();
- RGuard(guards);
- while (la->kind == 13 /* "," */) {
- Get();
- RGuard(guards);
- }
- }
- Expect(19 /* "{" */);
- RBody(args, guards);
- Expect(21 /* "}" */);
-}
-
-void Parser::PassData() {
- Expect(29 /* "pass" */);
- Expect(_lparen);
- Expect(_ident);
- Expect(_rparen);
- Expect(19 /* "{" */);
- while (la->kind == 30 /* "operator" */) {
- InDecl();
- }
- Expect(21 /* "}" */);
-}
-
-void Parser::Imprt() {
- Expect(27 /* "import" */);
- Expect(28 /* "raw" */);
- Expect(_lparen);
- Expect(_string);
- root.__rawImports.push_back(Atom<String_t>(t->val).get());
- Expect(_rparen);
- Expect(20 /* ";" */);
-}
-
-void Parser::Ident(std::wstring& name) {
- Expect(_ident);
- name = t->val;
-}
-
-void Parser::Type(TypeAnnotation& typ) {
- TypeAnnotation typ2; TypeAtom typ3;
- if (la->kind == _lbrack) {
- Get();
- Type(typ2);
- Expect(_rbrack);
- typ = TypeAnnotation(TypeOperator::LIST, {typ2});
- } else if (StartOf(3)) {
- TypeTerm(typ3);
- typ = TypeAnnotation(typ3);
- } else SynErr(50);
-}
-
-void Parser::FnTag(Function* f) {
- Expression tag; TagModifier mod = TagModifier::NONE;
- MetaSimpExpr(tag);
- if (la->kind == 34 /* "-" */) {
- Get();
- TagMod(mod);
- }
- f->addTag(std::move(tag), mod);
-}
-
-void Parser::BDecl(CodeScope* scope) {
- Expression body;
- Expect(19 /* "{" */);
- while (StartOf(4)) {
- if (checkAssignment()) {
- VDecl(scope);
- Expect(20 /* ";" */);
- } else if (la->kind == 12 /* ":" */) {
- TagsDecl(scope);
- Expect(20 /* ";" */);
- } else {
- Expr(body);
- Expect(20 /* ";" */);
- scope->setBody(body);
- }
- }
- Expect(21 /* "}" */);
-}
-
-void Parser::TypeTerm(TypeAtom& typ) {
- if (la->kind == 14 /* "string" */) {
- Get();
- } else if (la->kind == 15 /* "int" */) {
- Get();
- } else if (la->kind == 16 /* "num" */) {
- Get();
- } else if (la->kind == 17 /* "float" */) {
- Get();
- } else if (la->kind == 18 /* "bool" */) {
- Get();
- } else SynErr(51);
- typ = Atom<Type_t>(t->val);
-}
-
-void Parser::VDecl(CodeScope* f) {
- std::wstring vname; Expression e; TypeAnnotation typ;
- Ident(vname);
- Expect(_assign);
- if (la->kind == _lbrack) {
- ListLiteral(e);
- Expect(12 /* ":" */);
- Type(typ);
- } else if (la->kind == 24 /* "loop" */) {
- LoopDecl(e, typ, f);
- } else if (la->kind == 22 /* "if" */) {
- IfDecl(e, f, typ);
- } else if (StartOf(5)) {
- Expr(e);
- Expect(12 /* ":" */);
- Type(typ);
- } else SynErr(52);
- f->addDeclaration(move(vname), move(typ), move(e));
-}
-
-void Parser::ListLiteral(Expression& e) {
- Expression eFrom, eTo;
- Expect(_lbrack);
- if (StartOf(5)) {
- Expr(eFrom);
- e.addArg(std::move(eFrom));
- if (la->kind == 42 /* ".." */) {
- Get();
- Expr(eTo);
- e.addArg(std::move(eTo)); e.setOp(Operator::LIST_RANGE);
- } else if (la->kind == _rbrack || la->kind == 13 /* "," */) {
- while (la->kind == 13 /* "," */) {
- Get();
- Expr(eFrom);
- e.addArg(std::move(eFrom));
- }
- e.setOp(Operator::LIST);
- } else SynErr(53);
- }
- Expect(_rbrack);
-}
-
-void Parser::LoopDecl(Expression& e, TypeAnnotation& typOut, CodeScope* f) {
- std::wstring varIn, varEl, varAcc; TypeAnnotation typEl, typAcc; Expression eAcc;
- ManagedScpPtr block = root.add(new xreate::CodeScope(f));
- Expect(24 /* "loop" */);
- if (la->kind == 25 /* "map" */) {
- Get();
- Expect(_lparen);
- Ident(varIn);
- Expect(_implic);
- Ident(varEl);
- Expect(12 /* ":" */);
- Type(typEl);
- Expect(_rparen);
- Expect(12 /* ":" */);
- Type(typOut);
- BDecl(&*block);
- e = Expression(Operator::MAP, {Expression(Atom<Identifier_t>(varIn))});
- e.addBindings({Atom<Identifier_t>(varEl)});
- block->addArg(Atom<Identifier_t>(varEl), move(typEl));
- e.addBlock(block);
- } else if (la->kind == 26 /* "fold" */) {
- Get();
- Expect(_lparen);
- Ident(varIn);
- Expect(_implic);
- Ident(varEl);
- Expect(12 /* ":" */);
- Type(typEl);
- Expect(13 /* "," */);
- Expr(eAcc);
- Expect(_implic);
- Ident(varAcc);
- Expect(12 /* ":" */);
- Type(typAcc);
- Expect(_rparen);
- Expect(12 /* ":" */);
- Type(typOut);
- BDecl(&*block);
- e = Expression(Operator::FOLD, {Expression(Atom<Identifier_t>(varIn)), eAcc});
- e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
- block->addArg(Atom<Identifier_t>(varEl), move(typEl));
- block->addArg(Atom<Identifier_t>(varAcc), move(typAcc));
- e.addBlock(block);
-
- } else SynErr(54);
-}
-
-void Parser::IfDecl(Expression& e, CodeScope* outer, TypeAnnotation typ) {
- Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(outer)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(outer));
- TypeAnnotation typIf;
- Expect(22 /* "if" */);
- Expect(_lparen);
- Expr(cond);
- Expect(_rparen);
- Expect(12 /* ":" */);
- Type(typIf);
- BDecl(&*blockTrue);
- Expect(23 /* "else" */);
- BDecl(&*blockFalse);
- e = Expression(Operator::IF, {cond}); e.addBlock(blockTrue); e.addBlock(blockFalse);
-}
-
-void Parser::Expr(Expression& e) {
- Operator op; Expression e2;
- SimExpr(e);
- if (la->kind == _equal || la->kind == 46 /* "<" */ || la->kind == 47 /* ">" */) {
- RelOp(op);
- SimExpr(e2);
- e = Expression(op, {e, e2});
- }
-}
-
-void Parser::TagsDecl(CodeScope* f) {
- Expression tag; TagModifier mod = TagModifier::NONE;
- Expect(12 /* ":" */);
- while (la->kind == _ident || la->kind == 34 /* "-" */) {
- MetaSimpExpr(tag);
- if (la->kind == 34 /* "-" */) {
- Get();
- TagMod(mod);
- }
-
- }
-}
-
-void Parser::InDecl() {
- Operator op; Expression tag;
- Expression scheme;
- std::vector<Expression>& tags = scheme.operands;
- tags.push_back(Expression()); /* return value */
- Expect(30 /* "operator" */);
- InAlias(op);
- Expect(12 /* ":" */);
- Expect(_lparen);
- scheme.setOp(op);
- if (la->kind == _ident || la->kind == 34 /* "-" */) {
- MetaSimpExpr(tag);
- tags.push_back(tag);
- while (la->kind == 13 /* "," */) {
- Get();
- MetaSimpExpr(tag);
- tags.push_back(tag);
- }
- }
- Expect(_rparen);
- if (la->kind == _implic) {
- Get();
- MetaSimpExpr(tag);
- tags[0] = tag;
- }
- root.addDFAData(move(scheme));
- Expect(20 /* ";" */);
-}
-
-void Parser::InAlias(Operator& op) {
- if (la->kind == 25 /* "map" */) {
- Get();
- op = Operator::MAP;
- } else if (la->kind == 31 /* "list_range" */) {
- Get();
- op = Operator::LIST_RANGE;
- } else if (la->kind == 32 /* "list" */) {
- Get();
- op = Operator::LIST;
- } else if (la->kind == 26 /* "fold" */) {
- Get();
- op = Operator::FOLD;
- } else if (la->kind == 33 /* "index" */) {
- Get();
- op = Operator::INDEX;
- } else SynErr(55);
-}
-
-void Parser::MetaSimpExpr(Expression& e) {
- std::wstring i1, infix; Expression e2;
- if (la->kind == 34 /* "-" */) {
- Get();
- MetaSimpExpr(e2);
- e = Expression(Operator::NEG, {e2});
- } else if (checkParametersList()) {
- Ident(i1);
- e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))});
- Expect(_lparen);
- if (StartOf(5)) {
- CalleeParams(e);
- }
- Expect(_rparen);
- } else 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));
-
- } else if (la->kind == _ident) {
- Ident(i1);
- e = Expression(Atom<Identifier_t>(i1));
- } else SynErr(56);
-}
-
-void Parser::TagMod(TagModifier& mod) {
- if (la->kind == 35 /* "assert" */) {
- Get();
- mod = TagModifier::ASSERT;
- } else if (la->kind == 36 /* "require" */) {
- Get();
- mod = TagModifier::REQUIRE;
- } else SynErr(57);
-}
-
-void Parser::Domain(DomainAnnotation& dom) {
- if (la->kind == 11 /* "function" */) {
- Get();
- dom = DomainAnnotation::FUNCTION;
- } else if (la->kind == 39 /* "variable" */) {
- Get();
- dom = DomainAnnotation::VARIABLE;
- } else SynErr(58);
-}
-
-void Parser::RGuard(RuleGuards& guards) {
- Expression e;
- MetaExpr(e);
- guards.add(std::move(e));
-}
-
-void Parser::RBody(const RuleArguments& args, const RuleGuards& guards) {
- Expression e; std::wstring msg;
- Expect(40 /* "warning" */);
- MetaExpr(e);
- if (la->kind == 41 /* "message" */) {
- Get();
- Expect(_string);
- msg = t->val;
- }
- root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg)));
-}
-
-void Parser::MetaExpr(Expression& e) {
- Operator op; Expression e2;
- MetaExpr2(e);
- if (la->kind == _implic) {
- MetaOp(op);
- MetaExpr2(e2);
- e = Expression(op, {e, e2});
- }
-}
-
-void Parser::MetaExpr2(Expression& e) {
- if (la->kind == _lparen) {
- Get();
- MetaExpr(e);
- Expect(_rparen);
- } else if (la->kind == _ident || la->kind == 34 /* "-" */) {
- MetaSimpExpr(e);
- } else SynErr(59);
-}
-
-void Parser::MetaOp(Operator& op) {
- Expect(_implic);
- op = Operator::IMPL;
-}
-
-void Parser::CalleeParams(Expression& e) {
- Expression e2;
- Expr(e2);
- e.addArg(std::move(e2));
- while (la->kind == 13 /* "," */) {
- Get();
- Expr(e2);
- e.addArg(std::move(e2));
- }
-}
-
-void Parser::SimExpr(Expression& e) {
- Operator op; Expression e2;
- Term(e);
- while (la->kind == 34 /* "-" */ || la->kind == 43 /* "+" */) {
- AddOp(op);
- Term(e2);
- e = Expression(op, {e, e2});
- }
-}
-
-void Parser::RelOp(Operator& op) {
- op = Operator::EQU;
- if (la->kind == _equal) {
- Get();
- } else if (la->kind == 46 /* "<" */) {
- Get();
- op = Operator::LSS;
- } else if (la->kind == 47 /* ">" */) {
- Get();
- op = Operator::GTR;
- } else SynErr(60);
-}
-
-void Parser::Term(Expression& e) {
- Operator op; Expression e2;
- Factor(e);
- while (la->kind == 44 /* "*" */ || la->kind == 45 /* "/" */) {
- MulOp(op);
- Factor(e2);
- e = Expression(op, {e, e2});
- }
-}
-
-void Parser::AddOp(Operator& op) {
- op = Operator::ADD;
- if (la->kind == 43 /* "+" */) {
- Get();
- } else if (la->kind == 34 /* "-" */) {
- Get();
- op = Operator::SUB;
- } else SynErr(61);
-}
-
-void Parser::Factor(Expression& e) {
- std::wstring name;
- if (checkParametersList()) {
- Ident(name);
- e = Expression(Operator::CALL, {Atom<Identifier_t>(name)});
- Expect(_lparen);
- if (StartOf(5)) {
- CalleeParams(e);
- }
- Expect(_rparen);
- } else if (checkIndex()) {
- Ident(name);
- e = Expression(Operator::INDEX, {Atom<Identifier_t>(name)});
- Expect(_lbrack);
- CalleeParams(e);
- Expect(_rbrack);
- } else if (la->kind == _ident) {
- Ident(name);
- e = Expression(Atom<Identifier_t>(name));
- } else if (la->kind == _number) {
- Get();
- e = Expression(Atom<Number_t>(t->val));
- } else if (la->kind == 34 /* "-" */) {
- Get();
- Factor(e);
- e = Expression(Operator::NEG, {e});
- } else if (la->kind == _lparen) {
- Get();
- Expr(e);
- Expect(_rparen);
- } else SynErr(62);
-}
-
-void Parser::MulOp(Operator& op) {
- op = Operator::MUL;
- if (la->kind == 44 /* "*" */) {
- Get();
- } else if (la->kind == 45 /* "/" */) {
- Get();
- op = Operator::DIV;
- } else SynErr(63);
-}
-
-
-
-
-// If the user declared a method Init and a mehtod Destroy they should
-// be called in the contructur and the destructor respctively.
-//
-// The following templates are used to recognize if the user declared
-// the methods Init and Destroy.
-
-template<typename T>
-struct ParserInitExistsRecognizer {
- template<typename U, void (U::*)() = &U::Init>
- struct ExistsIfInitIsDefinedMarker{};
-
- struct InitIsMissingType {
- char dummy1;
- };
-
- struct InitExistsType {
- char dummy1; char dummy2;
- };
-
- // exists always
- template<typename U>
- static InitIsMissingType is_here(...);
-
- // exist only if ExistsIfInitIsDefinedMarker is defined
- template<typename U>
- static InitExistsType is_here(ExistsIfInitIsDefinedMarker<U>*);
-
- enum { InitExists = (sizeof(is_here<T>(NULL)) == sizeof(InitExistsType)) };
-};
-
-template<typename T>
-struct ParserDestroyExistsRecognizer {
- template<typename U, void (U::*)() = &U::Destroy>
- struct ExistsIfDestroyIsDefinedMarker{};
-
- struct DestroyIsMissingType {
- char dummy1;
- };
-
- struct DestroyExistsType {
- char dummy1; char dummy2;
- };
-
- // exists always
- template<typename U>
- static DestroyIsMissingType is_here(...);
-
- // exist only if ExistsIfDestroyIsDefinedMarker is defined
- template<typename U>
- static DestroyExistsType is_here(ExistsIfDestroyIsDefinedMarker<U>*);
-
- enum { DestroyExists = (sizeof(is_here<T>(NULL)) == sizeof(DestroyExistsType)) };
-};
-
-// The folloing templates are used to call the Init and Destroy methods if they exist.
-
-// Generic case of the ParserInitCaller, gets used if the Init method is missing
-template<typename T, bool = ParserInitExistsRecognizer<T>::InitExists>
-struct ParserInitCaller {
- static void CallInit(T *t) {
- // nothing to do
- }
-};
-
-// True case of the ParserInitCaller, gets used if the Init method exists
-template<typename T>
-struct ParserInitCaller<T, true> {
- static void CallInit(T *t) {
- t->Init();
- }
-};
-
-// Generic case of the ParserDestroyCaller, gets used if the Destroy method is missing
-template<typename T, bool = ParserDestroyExistsRecognizer<T>::DestroyExists>
-struct ParserDestroyCaller {
- static void CallDestroy(T *t) {
- // nothing to do
- }
-};
-
-// True case of the ParserDestroyCaller, gets used if the Destroy method exists
-template<typename T>
-struct ParserDestroyCaller<T, true> {
- static void CallDestroy(T *t) {
- t->Destroy();
- }
-};
-
-void Parser::Parse() {
- t = NULL;
- la = dummyToken = new Token();
- la->val = coco_string_create(L"Dummy Token");
- Get();
- Xreate();
- Expect(0);
-}
-
-Parser::Parser(Scanner *scanner) {
- maxT = 48;
-
- ParserInitCaller<Parser>::CallInit(this);
- dummyToken = NULL;
- t = la = NULL;
- minErrDist = 2;
- errDist = minErrDist;
- this->scanner = scanner;
- errors = new Errors();
-}
-
-bool Parser::StartOf(int s) {
- const bool T = true;
- const bool x = false;
-
- static bool set[6][50] = {
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,T,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,x, x,x,x,x, x,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,x, T,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}
- };
-
-
-
- return set[s][la->kind];
-}
-
-Parser::~Parser() {
- ParserDestroyCaller<Parser>::CallDestroy(this);
- delete errors;
- delete dummyToken;
-}
-
-Errors::Errors() {
- count = 0;
-}
-
-void Errors::SynErr(int line, int col, int n) {
- wchar_t* s;
- switch (n) {
- case 0: s = coco_string_create(L"EOF expected"); break;
- case 1: s = coco_string_create(L"ident expected"); break;
- case 2: s = coco_string_create(L"number expected"); break;
- case 3: s = coco_string_create(L"string expected"); break;
- case 4: s = coco_string_create(L"lparen expected"); break;
- case 5: s = coco_string_create(L"rparen expected"); break;
- case 6: s = coco_string_create(L"lbrack expected"); break;
- case 7: s = coco_string_create(L"rbrack expected"); break;
- case 8: s = coco_string_create(L"equal expected"); break;
- case 9: s = coco_string_create(L"assign expected"); break;
- case 10: s = coco_string_create(L"implic expected"); break;
- case 11: s = coco_string_create(L"\"function\" expected"); break;
- case 12: s = coco_string_create(L"\":\" expected"); break;
- case 13: s = coco_string_create(L"\",\" expected"); break;
- case 14: s = coco_string_create(L"\"string\" expected"); break;
- case 15: s = coco_string_create(L"\"int\" expected"); break;
- case 16: s = coco_string_create(L"\"num\" expected"); break;
- case 17: s = coco_string_create(L"\"float\" expected"); break;
- case 18: s = coco_string_create(L"\"bool\" expected"); break;
- case 19: s = coco_string_create(L"\"{\" expected"); break;
- case 20: s = coco_string_create(L"\";\" expected"); break;
- case 21: s = coco_string_create(L"\"}\" expected"); break;
- case 22: s = coco_string_create(L"\"if\" expected"); break;
- case 23: s = coco_string_create(L"\"else\" expected"); break;
- case 24: s = coco_string_create(L"\"loop\" expected"); break;
- case 25: s = coco_string_create(L"\"map\" expected"); break;
- case 26: s = coco_string_create(L"\"fold\" expected"); break;
- case 27: s = coco_string_create(L"\"import\" expected"); break;
- case 28: s = coco_string_create(L"\"raw\" expected"); break;
- case 29: s = coco_string_create(L"\"pass\" expected"); break;
- case 30: s = coco_string_create(L"\"operator\" expected"); break;
- case 31: s = coco_string_create(L"\"list_range\" expected"); break;
- case 32: s = coco_string_create(L"\"list\" expected"); break;
- case 33: s = coco_string_create(L"\"index\" expected"); break;
- case 34: s = coco_string_create(L"\"-\" expected"); break;
- case 35: s = coco_string_create(L"\"assert\" expected"); break;
- case 36: s = coco_string_create(L"\"require\" expected"); break;
- case 37: s = coco_string_create(L"\"rule\" expected"); break;
- case 38: s = coco_string_create(L"\"case\" expected"); break;
- case 39: s = coco_string_create(L"\"variable\" expected"); break;
- case 40: s = coco_string_create(L"\"warning\" expected"); break;
- case 41: s = coco_string_create(L"\"message\" expected"); break;
- case 42: s = coco_string_create(L"\"..\" expected"); break;
- case 43: s = coco_string_create(L"\"+\" expected"); break;
- case 44: s = coco_string_create(L"\"*\" expected"); break;
- case 45: s = coco_string_create(L"\"/\" expected"); break;
- case 46: s = coco_string_create(L"\"<\" expected"); break;
- case 47: s = coco_string_create(L"\">\" expected"); break;
- case 48: s = coco_string_create(L"??? expected"); break;
- case 49: s = coco_string_create(L"invalid FDecl"); break;
- case 50: s = coco_string_create(L"invalid Type"); break;
- case 51: s = coco_string_create(L"invalid TypeTerm"); break;
- case 52: s = coco_string_create(L"invalid VDecl"); break;
- case 53: s = coco_string_create(L"invalid ListLiteral"); break;
- case 54: s = coco_string_create(L"invalid LoopDecl"); break;
- case 55: s = coco_string_create(L"invalid InAlias"); break;
- case 56: s = coco_string_create(L"invalid MetaSimpExpr"); break;
- case 57: s = coco_string_create(L"invalid TagMod"); break;
- case 58: s = coco_string_create(L"invalid Domain"); break;
- case 59: s = coco_string_create(L"invalid MetaExpr2"); break;
- case 60: s = coco_string_create(L"invalid RelOp"); break;
- case 61: s = coco_string_create(L"invalid AddOp"); break;
- case 62: s = coco_string_create(L"invalid Factor"); break;
- case 63: s = coco_string_create(L"invalid MulOp"); break;
-
- default:
- {
- wchar_t format[20];
- coco_swprintf(format, 20, L"error %d", n);
- s = coco_string_create(format);
- }
- break;
- }
- wprintf(L"-- line %d col %d: %ls\n", line, col, s);
- coco_string_delete(s);
- count++;
-}
-
-void Errors::Error(int line, int col, const wchar_t *s) {
- wprintf(L"-- line %d col %d: %ls\n", line, col, s);
- count++;
-}
-
-void Errors::Warning(int line, int col, const wchar_t *s) {
- wprintf(L"-- line %d col %d: %ls\n", line, col, s);
-}
-
-void Errors::Warning(const wchar_t *s) {
- wprintf(L"%ls\n", s);
-}
-
-void Errors::Exception(const wchar_t* s) {
- wprintf(L"%ls", s);
- exit(1);
-}
-
-
diff --git a/coco/Parser.h b/coco/Parser.h
deleted file mode 100644
index 56d39cd..0000000
--- a/coco/Parser.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*----------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported to C++ by Csaba Balazs, University of Szeged
-with improvements by Pat Terry, Rhodes University
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than
-Coco/R itself) does not fall under the GNU General Public License.
------------------------------------------------------------------------*/
-
-
-#if !defined(COCO_PARSER_H__)
-#define COCO_PARSER_H__
-
-#include "ast.h"
-#include <string>
-
-using namespace xreate;
-using namespace std;
-
-
-#include "Scanner.h"
-
-
-
-class Errors {
-public:
- int count; // number of errors detected
-
- Errors();
- void SynErr(int line, int col, int n);
- void Error(int line, int col, const wchar_t *s);
- void Warning(int line, int col, const wchar_t *s);
- void Warning(const wchar_t *s);
- void Exception(const wchar_t *s);
-
-}; // Errors
-
-class Parser {
-private:
- enum {
- _EOF=0,
- _ident=1,
- _number=2,
- _string=3,
- _lparen=4,
- _rparen=5,
- _lbrack=6,
- _rbrack=7,
- _equal=8,
- _assign=9,
- _implic=10
- };
- int maxT;
-
- Token *dummyToken;
- int errDist;
- int minErrDist;
-
- void SynErr(int n);
- void Get();
- void Expect(int n);
- bool StartOf(int s);
- void ExpectWeak(int n, int follow);
- bool WeakSeparator(int n, int syFol, int repFol);
-
-public:
- Scanner *scanner;
- Errors *errors;
-
- Token *t; // last recognized token
- Token *la; // lookahead token
-
-xreate::AST root; // current program unit
-
-bool checkParametersList()
-{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _lparen;
-}
-
-bool checkInfix()
-{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _ident;
-}
-
-bool checkIndex()
-{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _lbrack;
-}
-
-bool checkAssignment()
-{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _assign;
-}
-
-
-
- Parser(Scanner *scanner);
- ~Parser();
- void SemErr(const wchar_t* msg);
-
- void Xreate();
- void FDecl();
- void RuleDecl();
- void PassData();
- void Imprt();
- void Ident(std::wstring& name);
- void Type(TypeAnnotation& typ);
- void FnTag(Function* f);
- void BDecl(CodeScope* scope);
- void TypeTerm(TypeAtom& typ);
- void VDecl(CodeScope* f);
- void ListLiteral(Expression& e);
- void LoopDecl(Expression& e, TypeAnnotation& typOut, CodeScope* f);
- void IfDecl(Expression& e, CodeScope* outer, TypeAnnotation typ);
- void Expr(Expression& e);
- void TagsDecl(CodeScope* f);
- void InDecl();
- void InAlias(Operator& op);
- void MetaSimpExpr(Expression& e);
- void TagMod(TagModifier& mod);
- void Domain(DomainAnnotation& dom);
- void RGuard(RuleGuards& guards);
- void RBody(const RuleArguments& args, const RuleGuards& guards);
- void MetaExpr(Expression& e);
- void MetaExpr2(Expression& e);
- void MetaOp(Operator& op);
- void CalleeParams(Expression& e);
- void SimExpr(Expression& e);
- void RelOp(Operator& op);
- void Term(Expression& e);
- void AddOp(Operator& op);
- void Factor(Expression& e);
- void MulOp(Operator& op);
-
- void Parse();
-
-}; // end Parser
-
-
-
-#endif
-
diff --git a/coco/Scanner.cpp b/coco/Scanner.cpp
deleted file mode 100644
index 72d3c7c..0000000
--- a/coco/Scanner.cpp
+++ /dev/null
@@ -1,788 +0,0 @@
-/*----------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported to C++ by Csaba Balazs, University of Szeged
-with improvements by Pat Terry, Rhodes University
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than
-Coco/R itself) does not fall under the GNU General Public License.
------------------------------------------------------------------------*/
-
-
-#include <memory.h>
-#include <string.h>
-#include "Scanner.h"
-
-
-
-
-// string handling, wide character
-
-
-wchar_t* coco_string_create(const wchar_t* value) {
- return coco_string_create(value, 0);
-}
-
-wchar_t* coco_string_create(const wchar_t *value, int startIndex) {
- int valueLen = 0;
- int len = 0;
-
- if (value) {
- valueLen = wcslen(value);
- len = valueLen - startIndex;
- }
-
- return coco_string_create(value, startIndex, len);
-}
-
-wchar_t* coco_string_create(const wchar_t *value, int startIndex, int length) {
- int len = 0;
- wchar_t* data;
-
- if (value) { len = length; }
- data = new wchar_t[len + 1];
- wcsncpy(data, &(value[startIndex]), len);
- data[len] = 0;
-
- return data;
-}
-
-wchar_t* coco_string_create_upper(const wchar_t* data) {
- if (!data) { return NULL; }
-
- int dataLen = 0;
- if (data) { dataLen = wcslen(data); }
-
- wchar_t *newData = new wchar_t[dataLen + 1];
-
- for (int i = 0; i <= dataLen; i++) {
- if ((L'a' <= data[i]) && (data[i] <= L'z')) {
- newData[i] = data[i] + (L'A' - L'a');
- }
- else { newData[i] = data[i]; }
- }
-
- newData[dataLen] = L'\0';
- return newData;
-}
-
-wchar_t* coco_string_create_lower(const wchar_t* data) {
- if (!data) { return NULL; }
- int dataLen = wcslen(data);
- return coco_string_create_lower(data, 0, dataLen);
-}
-
-wchar_t* coco_string_create_lower(const wchar_t* data, int startIndex, int dataLen) {
- if (!data) { return NULL; }
-
- wchar_t* newData = new wchar_t[dataLen + 1];
-
- for (int i = 0; i <= dataLen; i++) {
- wchar_t ch = data[startIndex + i];
- if ((L'A' <= ch) && (ch <= L'Z')) {
- newData[i] = ch - (L'A' - L'a');
- }
- else { newData[i] = ch; }
- }
- newData[dataLen] = L'\0';
- return newData;
-}
-
-wchar_t* coco_string_create_append(const wchar_t* data1, const wchar_t* data2) {
- wchar_t* data;
- int data1Len = 0;
- int data2Len = 0;
-
- if (data1) { data1Len = wcslen(data1); }
- if (data2) {data2Len = wcslen(data2); }
-
- data = new wchar_t[data1Len + data2Len + 1];
-
- if (data1) { wcscpy(data, data1); }
- if (data2) { wcscpy(data + data1Len, data2); }
-
- data[data1Len + data2Len] = 0;
-
- return data;
-}
-
-wchar_t* coco_string_create_append(const wchar_t *target, const wchar_t appendix) {
- int targetLen = coco_string_length(target);
- wchar_t* data = new wchar_t[targetLen + 2];
- wcsncpy(data, target, targetLen);
- data[targetLen] = appendix;
- data[targetLen + 1] = 0;
- return data;
-}
-
-void coco_string_delete(wchar_t* &data) {
- delete [] data;
- data = NULL;
-}
-
-int coco_string_length(const wchar_t* data) {
- if (data) { return wcslen(data); }
- return 0;
-}
-
-bool coco_string_endswith(const wchar_t* data, const wchar_t *end) {
- int dataLen = wcslen(data);
- int endLen = wcslen(end);
- return (endLen <= dataLen) && (wcscmp(data + dataLen - endLen, end) == 0);
-}
-
-int coco_string_indexof(const wchar_t* data, const wchar_t value) {
- const wchar_t* chr = wcschr(data, value);
-
- if (chr) { return (chr-data); }
- return -1;
-}
-
-int coco_string_lastindexof(const wchar_t* data, const wchar_t value) {
- const wchar_t* chr = wcsrchr(data, value);
-
- if (chr) { return (chr-data); }
- return -1;
-}
-
-void coco_string_merge(wchar_t* &target, const wchar_t* appendix) {
- if (!appendix) { return; }
- wchar_t* data = coco_string_create_append(target, appendix);
- delete [] target;
- target = data;
-}
-
-bool coco_string_equal(const wchar_t* data1, const wchar_t* data2) {
- return wcscmp( data1, data2 ) == 0;
-}
-
-int coco_string_compareto(const wchar_t* data1, const wchar_t* data2) {
- return wcscmp(data1, data2);
-}
-
-int coco_string_hash(const wchar_t *data) {
- int h = 0;
- if (!data) { return 0; }
- while (*data != 0) {
- h = (h * 7) ^ *data;
- ++data;
- }
- if (h < 0) { h = -h; }
- return h;
-}
-
-// string handling, ascii character
-
-wchar_t* coco_string_create(const char* value) {
- int len = 0;
- if (value) { len = strlen(value); }
- wchar_t* data = new wchar_t[len + 1];
- for (int i = 0; i < len; ++i) { data[i] = (wchar_t) value[i]; }
- data[len] = 0;
- return data;
-}
-
-char* coco_string_create_char(const wchar_t *value) {
- int len = coco_string_length(value);
- char *res = new char[len + 1];
- for (int i = 0; i < len; ++i) { res[i] = (char) value[i]; }
- res[len] = 0;
- return res;
-}
-
-void coco_string_delete(char* &data) {
- delete [] data;
- data = NULL;
-}
-
-
-Token::Token() {
- kind = 0;
- pos = 0;
- col = 0;
- line = 0;
- val = NULL;
- next = NULL;
-}
-
-Token::~Token() {
- coco_string_delete(val);
-}
-
-Buffer::Buffer(FILE* s, bool isUserStream) {
-// ensure binary read on windows
-#if _MSC_VER >= 1300
- _setmode(_fileno(s), _O_BINARY);
-#endif
- stream = s; this->isUserStream = isUserStream;
- if (CanSeek()) {
- fseek(s, 0, SEEK_END);
- fileLen = ftell(s);
- fseek(s, 0, SEEK_SET);
- bufLen = (fileLen < COCO_MAX_BUFFER_LENGTH) ? fileLen : COCO_MAX_BUFFER_LENGTH;
- bufStart = INT_MAX; // nothing in the buffer so far
- } else {
- fileLen = bufLen = bufStart = 0;
- }
- bufCapacity = (bufLen>0) ? bufLen : COCO_MIN_BUFFER_LENGTH;
- buf = new unsigned char[bufCapacity];
- if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start)
- else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
- if (bufLen == fileLen && CanSeek()) Close();
-}
-
-Buffer::Buffer(Buffer *b) {
- buf = b->buf;
- bufCapacity = b->bufCapacity;
- b->buf = NULL;
- bufStart = b->bufStart;
- bufLen = b->bufLen;
- fileLen = b->fileLen;
- bufPos = b->bufPos;
- stream = b->stream;
- b->stream = NULL;
- isUserStream = b->isUserStream;
-}
-
-Buffer::Buffer(const unsigned char* buf, int len) {
- this->buf = new unsigned char[len];
- memcpy(this->buf, buf, len*sizeof(unsigned char));
- bufStart = 0;
- bufCapacity = bufLen = len;
- fileLen = len;
- bufPos = 0;
- stream = NULL;
-}
-
-Buffer::~Buffer() {
- Close();
- if (buf != NULL) {
- delete [] buf;
- buf = NULL;
- }
-}
-
-void Buffer::Close() {
- if (!isUserStream && stream != NULL) {
- fclose(stream);
- stream = NULL;
- }
-}
-
-int Buffer::Read() {
- if (bufPos < bufLen) {
- return buf[bufPos++];
- } else if (GetPos() < fileLen) {
- SetPos(GetPos()); // shift buffer start to Pos
- return buf[bufPos++];
- } else if ((stream != NULL) && !CanSeek() && (ReadNextStreamChunk() > 0)) {
- return buf[bufPos++];
- } else {
- return EoF;
- }
-}
-
-int Buffer::Peek() {
- int curPos = GetPos();
- int ch = Read();
- SetPos(curPos);
- return ch;
-}
-
-// beg .. begin, zero-based, inclusive, in byte
-// end .. end, zero-based, exclusive, in byte
-wchar_t* Buffer::GetString(int beg, int end) {
- int len = 0;
- wchar_t *buf = new wchar_t[end - beg];
- int oldPos = GetPos();
- SetPos(beg);
- while (GetPos() < end) buf[len++] = (wchar_t) Read();
- SetPos(oldPos);
- wchar_t *res = coco_string_create(buf, 0, len);
- coco_string_delete(buf);
- return res;
-}
-
-int Buffer::GetPos() {
- return bufPos + bufStart;
-}
-
-void Buffer::SetPos(int value) {
- if ((value >= fileLen) && (stream != NULL) && !CanSeek()) {
- // Wanted position is after buffer and the stream
- // is not seek-able e.g. network or console,
- // thus we have to read the stream manually till
- // the wanted position is in sight.
- while ((value >= fileLen) && (ReadNextStreamChunk() > 0));
- }
-
- if ((value < 0) || (value > fileLen)) {
- wprintf(L"--- buffer out of bounds access, position: %d\n", value);
- exit(1);
- }
-
- if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer
- bufPos = value - bufStart;
- } else if (stream != NULL) { // must be swapped in
- fseek(stream, value, SEEK_SET);
- bufLen = fread(buf, sizeof(unsigned char), bufCapacity, stream);
- bufStart = value; bufPos = 0;
- } else {
- bufPos = fileLen - bufStart; // make Pos return fileLen
- }
-}
-
-// Read the next chunk of bytes from the stream, increases the buffer
-// if needed and updates the fields fileLen and bufLen.
-// Returns the number of bytes read.
-int Buffer::ReadNextStreamChunk() {
- int free = bufCapacity - bufLen;
- if (free == 0) {
- // in the case of a growing input stream
- // we can neither seek in the stream, nor can we
- // foresee the maximum length, thus we must adapt
- // the buffer size on demand.
- bufCapacity = bufLen * 2;
- unsigned char *newBuf = new unsigned char[bufCapacity];
- memcpy(newBuf, buf, bufLen*sizeof(unsigned char));
- delete [] buf;
- buf = newBuf;
- free = bufLen;
- }
- int read = fread(buf + bufLen, sizeof(unsigned char), free, stream);
- if (read > 0) {
- fileLen = bufLen = (bufLen + read);
- return read;
- }
- // end of stream reached
- return 0;
-}
-
-bool Buffer::CanSeek() {
- return (stream != NULL) && (ftell(stream) != -1);
-}
-
-int UTF8Buffer::Read() {
- int ch;
- do {
- ch = Buffer::Read();
- // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
- } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF));
- if (ch < 128 || ch == EoF) {
- // nothing to do, first 127 chars are the same in ascii and utf8
- // 0xxxxxxx or end of file character
- } else if ((ch & 0xF0) == 0xF0) {
- // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x07; ch = Buffer::Read();
- int c2 = ch & 0x3F; ch = Buffer::Read();
- int c3 = ch & 0x3F; ch = Buffer::Read();
- int c4 = ch & 0x3F;
- ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
- } else if ((ch & 0xE0) == 0xE0) {
- // 1110xxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x0F; ch = Buffer::Read();
- int c2 = ch & 0x3F; ch = Buffer::Read();
- int c3 = ch & 0x3F;
- ch = (((c1 << 6) | c2) << 6) | c3;
- } else if ((ch & 0xC0) == 0xC0) {
- // 110xxxxx 10xxxxxx
- int c1 = ch & 0x1F; ch = Buffer::Read();
- int c2 = ch & 0x3F;
- ch = (c1 << 6) | c2;
- }
- return ch;
-}
-
-Scanner::Scanner(const unsigned char* buf, int len) {
- buffer = new Buffer(buf, len);
- Init();
-}
-
-Scanner::Scanner(const wchar_t* fileName) {
- FILE* stream;
- char *chFileName = coco_string_create_char(fileName);
- if ((stream = fopen(chFileName, "rb")) == NULL) {
- wprintf(L"--- Cannot open file %ls\n", fileName);
- exit(1);
- }
- coco_string_delete(chFileName);
- buffer = new Buffer(stream, false);
- Init();
-}
-
-Scanner::Scanner(FILE* s) {
- buffer = new Buffer(s, true);
- Init();
-}
-
-Scanner::~Scanner() {
- char* cur = (char*) firstHeap;
-
- while(cur != NULL) {
- cur = *(char**) (cur + COCO_HEAP_BLOCK_SIZE);
- free(firstHeap);
- firstHeap = cur;
- }
- delete [] tval;
- delete buffer;
-}
-
-void Scanner::Init() {
- EOL = '\n';
- eofSym = 0;
- maxT = 48;
- noSym = 48;
- int i;
- for (i = 65; i <= 90; ++i) start.set(i, 1);
- for (i = 97; i <= 122; ++i) start.set(i, 1);
- for (i = 48; i <= 57; ++i) start.set(i, 2);
- start.set(34, 3);
- start.set(40, 5);
- start.set(41, 6);
- start.set(91, 7);
- start.set(93, 8);
- start.set(61, 11);
- start.set(45, 24);
- start.set(58, 12);
- start.set(44, 13);
- start.set(123, 14);
- start.set(59, 15);
- start.set(125, 16);
- start.set(46, 17);
- start.set(43, 19);
- start.set(42, 20);
- start.set(47, 21);
- start.set(60, 22);
- start.set(62, 23);
- start.set(Buffer::EoF, -1);
- keywords.set(L"function", 11);
- keywords.set(L"string", 14);
- keywords.set(L"int", 15);
- keywords.set(L"num", 16);
- keywords.set(L"float", 17);
- keywords.set(L"bool", 18);
- keywords.set(L"if", 22);
- keywords.set(L"else", 23);
- keywords.set(L"loop", 24);
- keywords.set(L"map", 25);
- keywords.set(L"fold", 26);
- keywords.set(L"import", 27);
- keywords.set(L"raw", 28);
- keywords.set(L"pass", 29);
- keywords.set(L"operator", 30);
- keywords.set(L"list_range", 31);
- keywords.set(L"list", 32);
- keywords.set(L"index", 33);
- keywords.set(L"assert", 35);
- keywords.set(L"require", 36);
- keywords.set(L"rule", 37);
- keywords.set(L"case", 38);
- keywords.set(L"variable", 39);
- keywords.set(L"warning", 40);
- keywords.set(L"message", 41);
-
-
- tvalLength = 128;
- tval = new wchar_t[tvalLength]; // text of current token
-
- // COCO_HEAP_BLOCK_SIZE byte heap + pointer to next heap block
- heap = malloc(COCO_HEAP_BLOCK_SIZE + sizeof(void*));
- firstHeap = heap;
- heapEnd = (void**) (((char*) heap) + COCO_HEAP_BLOCK_SIZE);
- *heapEnd = 0;
- heapTop = heap;
- if (sizeof(Token) > COCO_HEAP_BLOCK_SIZE) {
- wprintf(L"--- Too small COCO_HEAP_BLOCK_SIZE\n");
- exit(1);
- }
-
- pos = -1; line = 1; col = 0; charPos = -1;
- oldEols = 0;
- NextCh();
- if (ch == 0xEF) { // check optional byte order mark for UTF-8
- NextCh(); int ch1 = ch;
- NextCh(); int ch2 = ch;
- if (ch1 != 0xBB || ch2 != 0xBF) {
- wprintf(L"Illegal byte order mark at start of file");
- exit(1);
- }
- Buffer *oldBuf = buffer;
- buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
- delete oldBuf; oldBuf = NULL;
- NextCh();
- }
-
-
- pt = tokens = CreateToken(); // first token is a dummy
-}
-
-void Scanner::NextCh() {
- if (oldEols > 0) { ch = EOL; oldEols--; }
- else {
- pos = buffer->GetPos();
- // buffer reads unicode chars, if UTF8 has been detected
- ch = buffer->Read(); col++; charPos++;
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL;
- if (ch == EOL) { line++; col = 0; }
- }
-
-}
-
-void Scanner::AddCh() {
- if (tlen >= tvalLength) {
- tvalLength *= 2;
- wchar_t *newBuf = new wchar_t[tvalLength];
- memcpy(newBuf, tval, tlen*sizeof(wchar_t));
- delete [] tval;
- tval = newBuf;
- }
- if (ch != Buffer::EoF) {
- tval[tlen++] = ch;
- NextCh();
- }
-}
-
-
-bool Scanner::Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
- NextCh();
- if (ch == L'/') {
- NextCh();
- for(;;) {
- if (ch == 10) {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- } else if (ch == buffer->EoF) return false;
- else NextCh();
- }
- } else {
- buffer->SetPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
- }
- return false;
-}
-
-bool Scanner::Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
- NextCh();
- if (ch == L'*') {
- NextCh();
- for(;;) {
- if (ch == L'*') {
- NextCh();
- if (ch == L'/') {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- }
- } else if (ch == L'/') {
- NextCh();
- if (ch == L'*') {
- level++; NextCh();
- }
- } else if (ch == buffer->EoF) return false;
- else NextCh();
- }
- } else {
- buffer->SetPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
- }
- return false;
-}
-
-
-void Scanner::CreateHeapBlock() {
- void* newHeap;
- char* cur = (char*) firstHeap;
-
- while(((char*) tokens < cur) || ((char*) tokens > (cur + COCO_HEAP_BLOCK_SIZE))) {
- cur = *((char**) (cur + COCO_HEAP_BLOCK_SIZE));
- free(firstHeap);
- firstHeap = cur;
- }
-
- // COCO_HEAP_BLOCK_SIZE byte heap + pointer to next heap block
- newHeap = malloc(COCO_HEAP_BLOCK_SIZE + sizeof(void*));
- *heapEnd = newHeap;
- heapEnd = (void**) (((char*) newHeap) + COCO_HEAP_BLOCK_SIZE);
- *heapEnd = 0;
- heap = newHeap;
- heapTop = heap;
-}
-
-Token* Scanner::CreateToken() {
- Token *t;
- if (((char*) heapTop + (int) sizeof(Token)) >= (char*) heapEnd) {
- CreateHeapBlock();
- }
- t = (Token*) heapTop;
- heapTop = (void*) ((char*) heapTop + sizeof(Token));
- t->val = NULL;
- t->next = NULL;
- return t;
-}
-
-void Scanner::AppendVal(Token *t) {
- int reqMem = (tlen + 1) * sizeof(wchar_t);
- if (((char*) heapTop + reqMem) >= (char*) heapEnd) {
- if (reqMem > COCO_HEAP_BLOCK_SIZE) {
- wprintf(L"--- Too long token value\n");
- exit(1);
- }
- CreateHeapBlock();
- }
- t->val = (wchar_t*) heapTop;
- heapTop = (void*) ((char*) heapTop + reqMem);
-
- wcsncpy(t->val, tval, tlen);
- t->val[tlen] = L'\0';
-}
-
-Token* Scanner::NextToken() {
- while (ch == ' ' ||
- (ch >= 9 && ch <= 10) || ch == 13
- ) NextCh();
- if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken();
- int recKind = noSym;
- int recEnd = pos;
- t = CreateToken();
- t->pos = pos; t->col = col; t->line = line; t->charPos = charPos;
- int state = start.state(ch);
- tlen = 0; AddCh();
-
- switch (state) {
- case -1: { t->kind = eofSym; break; } // NextCh already done
- case 0: {
- case_0:
- if (recKind != noSym) {
- tlen = recEnd - t->pos;
- SetScannerBehindT();
- }
- t->kind = recKind; break;
- } // NextCh already done
- case 1:
- case_1:
- recEnd = pos; recKind = 1;
- if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;}
- else {t->kind = 1; wchar_t *literal = coco_string_create(tval, 0, tlen); t->kind = keywords.get(literal, t->kind); coco_string_delete(literal); break;}
- case 2:
- case_2:
- recEnd = pos; recKind = 2;
- if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_2;}
- else {t->kind = 2; break;}
- case 3:
- case_3:
- if (ch <= L'!' || (ch >= L'#' && ch <= 65535)) {AddCh(); goto case_3;}
- else if (ch == L'"') {AddCh(); goto case_4;}
- else {goto case_0;}
- case 4:
- case_4:
- {t->kind = 3; break;}
- case 5:
- {t->kind = 4; break;}
- case 6:
- {t->kind = 5; break;}
- case 7:
- {t->kind = 6; break;}
- case 8:
- {t->kind = 7; break;}
- case 9:
- case_9:
- {t->kind = 8; break;}
- case 10:
- case_10:
- {t->kind = 10; break;}
- case 11:
- recEnd = pos; recKind = 9;
- if (ch == L'=') {AddCh(); goto case_9;}
- else {t->kind = 9; break;}
- case 12:
- {t->kind = 12; break;}
- case 13:
- {t->kind = 13; break;}
- case 14:
- {t->kind = 19; break;}
- case 15:
- {t->kind = 20; break;}
- case 16:
- {t->kind = 21; break;}
- case 17:
- if (ch == L'.') {AddCh(); goto case_18;}
- else {goto case_0;}
- case 18:
- case_18:
- {t->kind = 42; break;}
- case 19:
- {t->kind = 43; break;}
- case 20:
- {t->kind = 44; break;}
- case 21:
- {t->kind = 45; break;}
- case 22:
- {t->kind = 46; break;}
- case 23:
- {t->kind = 47; break;}
- case 24:
- recEnd = pos; recKind = 34;
- if (ch == L'>') {AddCh(); goto case_10;}
- else {t->kind = 34; break;}
-
- }
- AppendVal(t);
- return t;
-}
-
-void Scanner::SetScannerBehindT() {
- buffer->SetPos(t->pos);
- NextCh();
- line = t->line; col = t->col; charPos = t->charPos;
- for (int i = 0; i < tlen; i++) NextCh();
-}
-
-// get the next token (possibly a token already seen during peeking)
-Token* Scanner::Scan() {
- if (tokens->next == NULL) {
- return pt = tokens = NextToken();
- } else {
- pt = tokens = tokens->next;
- return tokens;
- }
-}
-
-// peek for the next token, ignore pragmas
-Token* Scanner::Peek() {
- do {
- if (pt->next == NULL) {
- pt->next = NextToken();
- }
- pt = pt->next;
- } while (pt->kind > maxT); // skip pragmas
-
- return pt;
-}
-
-// make sure that peeking starts at the current scan position
-void Scanner::ResetPeek() {
- pt = tokens;
-}
-
-
diff --git a/coco/Scanner.h b/coco/Scanner.h
deleted file mode 100644
index 9defd77..0000000
--- a/coco/Scanner.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/*----------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported to C++ by Csaba Balazs, University of Szeged
-with improvements by Pat Terry, Rhodes University
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than
-Coco/R itself) does not fall under the GNU General Public License.
------------------------------------------------------------------------*/
-
-
-#if !defined(COCO_SCANNER_H__)
-#define COCO_SCANNER_H__
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-
-// io.h and fcntl are used to ensure binary read from streams on windows
-#if _MSC_VER >= 1300
-#include <io.h>
-#include <fcntl.h>
-#endif
-
-#if _MSC_VER >= 1400
-#define coco_swprintf swprintf_s
-#elif _MSC_VER >= 1300
-#define coco_swprintf _snwprintf
-#elif defined __MINGW32__
-#define coco_swprintf _snwprintf
-#else
-// assume every other compiler knows swprintf
-#define coco_swprintf swprintf
-#endif
-
-#define COCO_WCHAR_MAX 65535
-#define COCO_MIN_BUFFER_LENGTH 1024
-#define COCO_MAX_BUFFER_LENGTH (64*COCO_MIN_BUFFER_LENGTH)
-#define COCO_HEAP_BLOCK_SIZE (64*1024)
-#define COCO_CPP_NAMESPACE_SEPARATOR L':'
-
-
-
-// string handling, wide character
-wchar_t* coco_string_create(const wchar_t *value);
-wchar_t* coco_string_create(const wchar_t *value, int startIndex);
-wchar_t* coco_string_create(const wchar_t *value, int startIndex, int length);
-wchar_t* coco_string_create_upper(const wchar_t* data);
-wchar_t* coco_string_create_lower(const wchar_t* data);
-wchar_t* coco_string_create_lower(const wchar_t* data, int startIndex, int dataLen);
-wchar_t* coco_string_create_append(const wchar_t* data1, const wchar_t* data2);
-wchar_t* coco_string_create_append(const wchar_t* data, const wchar_t value);
-void coco_string_delete(wchar_t* &data);
-int coco_string_length(const wchar_t* data);
-bool coco_string_endswith(const wchar_t* data, const wchar_t *value);
-int coco_string_indexof(const wchar_t* data, const wchar_t value);
-int coco_string_lastindexof(const wchar_t* data, const wchar_t value);
-void coco_string_merge(wchar_t* &data, const wchar_t* value);
-bool coco_string_equal(const wchar_t* data1, const wchar_t* data2);
-int coco_string_compareto(const wchar_t* data1, const wchar_t* data2);
-int coco_string_hash(const wchar_t* data);
-
-// string handling, ascii character
-wchar_t* coco_string_create(const char *value);
-char* coco_string_create_char(const wchar_t *value);
-void coco_string_delete(char* &data);
-
-
-class Token
-{
-public:
- int kind; // token kind
- int pos; // token position in bytes in the source text (starting at 0)
- int charPos; // token position in characters in the source text (starting at 0)
- int col; // token column (starting at 1)
- int line; // token line (starting at 1)
- wchar_t* val; // token value
- Token *next; // ML 2005-03-11 Peek tokens are kept in linked list
-
- Token();
- ~Token();
-};
-
-class Buffer {
-// This Buffer supports the following cases:
-// 1) seekable stream (file)
-// a) whole stream in buffer
-// b) part of stream in buffer
-// 2) non seekable stream (network, console)
-private:
- unsigned char *buf; // input buffer
- int bufCapacity; // capacity of buf
- int bufStart; // position of first byte in buffer relative to input stream
- int bufLen; // length of buffer
- int fileLen; // length of input stream (may change if the stream is no file)
- int bufPos; // current position in buffer
- FILE* stream; // input stream (seekable)
- bool isUserStream; // was the stream opened by the user?
-
- int ReadNextStreamChunk();
- bool CanSeek(); // true if stream can be seeked otherwise false
-
-public:
- static const int EoF = COCO_WCHAR_MAX + 1;
-
- Buffer(FILE* s, bool isUserStream);
- Buffer(const unsigned char* buf, int len);
- Buffer(Buffer *b);
- virtual ~Buffer();
-
- virtual void Close();
- virtual int Read();
- virtual int Peek();
- virtual wchar_t* GetString(int beg, int end);
- virtual int GetPos();
- virtual void SetPos(int value);
-};
-
-class UTF8Buffer : public Buffer {
-public:
- UTF8Buffer(Buffer *b) : Buffer(b) {};
- virtual int Read();
-};
-
-//-----------------------------------------------------------------------------------
-// StartStates -- maps characters to start states of tokens
-//-----------------------------------------------------------------------------------
-class StartStates {
-private:
- class Elem {
- public:
- int key, val;
- Elem *next;
- Elem(int key, int val) { this->key = key; this->val = val; next = NULL; }
- };
-
- Elem **tab;
-
-public:
- StartStates() { tab = new Elem*[128]; memset(tab, 0, 128 * sizeof(Elem*)); }
- virtual ~StartStates() {
- for (int i = 0; i < 128; ++i) {
- Elem *e = tab[i];
- while (e != NULL) {
- Elem *next = e->next;
- delete e;
- e = next;
- }
- }
- delete [] tab;
- }
-
- void set(int key, int val) {
- Elem *e = new Elem(key, val);
- int k = ((unsigned int) key) % 128;
- e->next = tab[k]; tab[k] = e;
- }
-
- int state(int key) {
- Elem *e = tab[((unsigned int) key) % 128];
- while (e != NULL && e->key != key) e = e->next;
- return e == NULL ? 0 : e->val;
- }
-};
-
-//-------------------------------------------------------------------------------------------
-// KeywordMap -- maps strings to integers (identifiers to keyword kinds)
-//-------------------------------------------------------------------------------------------
-class KeywordMap {
-private:
- class Elem {
- public:
- wchar_t *key;
- int val;
- Elem *next;
- Elem(const wchar_t *key, int val) { this->key = coco_string_create(key); this->val = val; next = NULL; }
- virtual ~Elem() { coco_string_delete(key); }
- };
-
- Elem **tab;
-
-public:
- KeywordMap() { tab = new Elem*[128]; memset(tab, 0, 128 * sizeof(Elem*)); }
- virtual ~KeywordMap() {
- for (int i = 0; i < 128; ++i) {
- Elem *e = tab[i];
- while (e != NULL) {
- Elem *next = e->next;
- delete e;
- e = next;
- }
- }
- delete [] tab;
- }
-
- void set(const wchar_t *key, int val) {
- Elem *e = new Elem(key, val);
- int k = coco_string_hash(key) % 128;
- e->next = tab[k]; tab[k] = e;
- }
-
- int get(const wchar_t *key, int defaultVal) {
- Elem *e = tab[coco_string_hash(key) % 128];
- while (e != NULL && !coco_string_equal(e->key, key)) e = e->next;
- return e == NULL ? defaultVal : e->val;
- }
-};
-
-class Scanner {
-private:
- void *firstHeap;
- void *heap;
- void *heapTop;
- void **heapEnd;
-
- unsigned char EOL;
- int eofSym;
- int noSym;
- int maxT;
- int charSetSize;
- StartStates start;
- KeywordMap keywords;
-
- Token *t; // current token
- wchar_t *tval; // text of current token
- int tvalLength; // length of text of current token
- int tlen; // length of current token
-
- Token *tokens; // list of tokens already peeked (first token is a dummy)
- Token *pt; // current peek token
-
- int ch; // current input character
-
- int pos; // byte position of current character
- int charPos; // position by unicode characters starting with 0
- int line; // line number of current character
- int col; // column number of current character
- int oldEols; // EOLs that appeared in a comment;
-
- void CreateHeapBlock();
- Token* CreateToken();
- void AppendVal(Token *t);
- void SetScannerBehindT();
-
- void Init();
- void NextCh();
- void AddCh();
- bool Comment0();
- bool Comment1();
-
- Token* NextToken();
-
-public:
- Buffer *buffer; // scanner buffer
-
- Scanner(const unsigned char* buf, int len);
- Scanner(const wchar_t* fileName);
- Scanner(FILE* s);
- ~Scanner();
- Token* Scan();
- Token* Peek();
- void ResetPeek();
-
-}; // end Scanner
-
-
-
-#endif
-
diff --git a/coco/xreate.ATG b/coco/xreate.ATG
index dab9e71..44ec3ed 100644
--- a/coco/xreate.ATG
+++ b/coco/xreate.ATG
@@ -1,293 +1,422 @@
+//TODO add ListLiteral
+//TODO ExprTyped: assign default(none) type
+
#include "ast.h"
+#include "ExternLayer.h"
#include <string>
+#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
-bool checkParametersList()
+int skipIdent()
{
+ int kind = 0;
scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _lparen;
+ while ((kind = scanner->Peek()->kind) == _colon)
+ if (scanner->Peek()->kind != _ident)
+ return 0;
+
+ return kind;
+}
+
+bool checkParametersList()
+{
+ return la->kind == _ident && skipIdent() == _lparen;
}
bool checkInfix()
{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _ident;
+ return la->kind == _ident && skipIdent() == _ident;
}
bool checkIndex()
{
- scanner->ResetPeek();
- Token* x = scanner->Peek();
- return la->kind == _ident && x->kind == _lbrack;
+ return la->kind == _ident && skipIdent() == _lbrack;
+}
+
+bool checkFuncDecl()
+{
+ if (la->kind != _ident) return false;
+
+ int xkind = skipIdent();
+ Token* y = scanner->Peek();
+ return xkind == _assign && y->kind == _function;
}
bool checkAssignment()
{
scanner->ResetPeek();
Token* x = scanner->Peek();
return la->kind == _ident && x->kind == _assign;
}
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
- ident = letter {letter | digit | '_'}.
+ ident = (letter | '_') {letter | digit | '_'}.
number = digit {digit}.
string = '"' { any } '"'.
+ function = "function".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
equal = "==".
assign = '='.
implic = '-' '>'.
+ colon = ':'.
+ tagcolon = "::".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
-Xreate = { ( FDecl | RuleDecl | PassData | Imprt) }.
+Xreate = { ( RuleDecl | InterfaceData | Imprt | IF(checkFuncDecl()) FDecl | TDecl ) }.
Ident<std::wstring& name>
-= ident (. name = t->val; .).
+= ident {':' ident} (. name = t->val; .).
FDecl<> = (. std::wstring fname; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut; .)
-Ident<fname> assign "function" ':' (. Function* f = new Function(fname); CodeScope* entry = f->getEntryScope(); .)
+Ident<fname> assign function (. Function* f = new Function(fname); CodeScope* entry = f->getEntryScope(); .)
( Type<typOut> (. f->setReturnType(typOut); .)
-| '(' [Ident<varname> ':' Type<typIn> (. f->addArg(std::move(varname), move(typIn)); .)
-{',' Ident<varname> ':' Type<typIn> (. f->addArg(std::move(varname), move(typIn));.)
-}] ')' implic Type<typOut> (. f->setReturnType(typOut); .)
-{',' FnTag<f> }
-) BDecl<entry> (. root.add(f); .)
+| '(' [Ident<varname> tagcolon Type<typIn> (. f->addArg(std::move(varname), move(typIn)); .)
+{',' Ident<varname> tagcolon Type<typIn> (. f->addArg(std::move(varname), move(typIn));.)
+}] ')' tagcolon Type<typOut> (. f->setReturnType(typOut); .)
+{';' FnTag<f> }
+) BDecl<entry> (. entry->__body.bindType(move(typOut)); root.add(f); .)
.
-TypeTerm<TypeAtom& typ> = ("string" | "int" | "num" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .) .
-Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; .)
-('[' Type<typ2> ']' (. typ = TypeAnnotation(TypeOperator::LIST, {typ2}); .)
+ /**
+ * TYPES
+ *
+ */
+TypeTerm<TypeAtom& typ> = (. std::wstring tid; .)
+ ("string" | "int" | "num" | "float" | "bool") (. typ = Atom<Type_t>(t->val); .)
+ .
+
+Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypeAtom typ3; std:wstring tid, field; .)
+(
+ TList<typ>
+| TStruct<typ>
| TypeTerm<typ3> (. typ = TypeAnnotation(typ3); .)
+|IF (checkIndex()) Ident<tid> lbrack
+ Ident<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
+ {',' Ident<field> (. typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
+ } rbrack
+
+| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
+ ['(' Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
+ {',' Type<typ2> (. typ.__operands.push_back(typ2); .)
+ } ')']
) .
-VDecl<CodeScope* f> = (. std::wstring vname; Expression e; TypeAnnotation typ; .)
-Ident<vname> assign
-(ListLiteral<e> ':' Type<typ>
-| LoopDecl<e, typ, f>
-| IfDecl<e, f, typ>
-| Expr<e> ':' Type<typ>
-) (. f->addDeclaration(move(vname), move(typ), move(e)); .).
+TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
+ '[' Type<ty> (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .)
+ {',' Type<ty> (. typ.__operator = TypeOperator::TUPLE; typ.__operands.push_back(ty); .)
+ }']'
+ .
+
+TStruct<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring field; .)
+ '{'
+ Ident<field> tagcolon Type<t> (. typ = TypeAnnotation(TypeOperator::STRUCT, {t}); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
+ {',' Ident<field> tagcolon Type<t>} (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
+ '}'.
+
+ TDecl = (. std::wstring ttag; TypeAnnotation t; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
+ Ident<tname> assign "type"
+ (
+ "alias" Type<t> (. root.add(move(t), Atom<Identifier_t>(tname)); .)
+ | Ident<ttag>
+ ['(' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
+ {',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
+ } ')']
+ Type<t> (. t.addBindings(move(args)); root.add(move(t), Atom<Identifier_t>(tname)); .)
+ ) '.'
+ .
+
+VDecl<CodeScope* f> = (. std::wstring vname; Expression e; TypeAnnotation typ;.)
+Ident<vname> assign ExprTyped<e, typ>
+ (. f->addDeclaration(move(vname), move(typ), move(e)); .)
+.
-BDecl<CodeScope* scope> = (. Expression body; .)
+BDecl<CodeScope* scope> = (. Expression body; TypeAnnotation typ; .)
'{' { (
- IF(checkAssignment()) VDecl<scope> ';'
- | TagsDecl<scope> ';'
- | Expr<body> ';' (. scope->setBody(body); .)
+ IF(checkAssignment()) VDecl<scope> '.'
+ | ExprTyped<body, typ> (. scope->setBody(body); .)
)}
'}'.
-IfDecl<Expression& e, CodeScope* outer, TypeAnnotation typ> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(outer)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(outer));
+IfDecl<Expression& e, TypeAnnotation typ, CodeScope* outer> = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(outer)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(outer));
TypeAnnotation typIf; .)
-"if" '(' Expr<cond> ')' ':' Type<typIf> BDecl<&*blockTrue> "else" BDecl<&*blockFalse>
+"if" '(' Expr<cond> ')' tagcolon Type<typIf> BDecl<&*blockTrue> "else" BDecl<&*blockFalse>
(. e = Expression(Operator::IF, {cond}); e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e, TypeAnnotation& typOut, CodeScope* f> =
- (. std::wstring varIn, varEl, varAcc; TypeAnnotation typEl, typAcc; Expression eAcc;
+ (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc; TypeAnnotation typEl, typAcc;
ManagedScpPtr block = root.add(new xreate::CodeScope(f)); .)
"loop"
- ("map" '(' Ident<varIn> implic Ident<varEl> ':' Type<typEl> ')' ':' Type<typOut> BDecl<&*block>
- (. e = Expression(Operator::MAP, {Expression(Atom<Identifier_t>(varIn))});
+ ("map" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ')' tagcolon Type<typOut> BDecl<&*block>
+ (. e = Expression(Operator::MAP, {eIn});
e.addBindings({Atom<Identifier_t>(varEl)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
e.addBlock(block); .)
- |"fold" '(' Ident<varIn> implic Ident<varEl> ':' Type<typEl> ',' Expr<eAcc> implic Ident<varAcc> ':' Type<typAcc> ')' ':' Type<typOut> BDecl<&*block>
- (. e = Expression(Operator::FOLD, {Expression(Atom<Identifier_t>(varIn)), eAcc});
+ |"fold" '(' Expr<eIn> implic Ident<varEl> tagcolon Type<typEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc> tagcolon Type<typAcc> ')' tagcolon Type<typOut> BDecl<&*block>
+ (. e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
block->addArg(Atom<Identifier_t>(varEl), move(typEl));
block->addArg(Atom<Identifier_t>(varAcc), move(typAcc));
e.addBlock(block);
.)
).
-
- /*============================ METAPROGRAMMING ===============================*/
-
+
+SwitchDecl<> = (. TypeAnnotation typ; Expression tag; .)
+ ["switch" [tagcolon Type<typ> {';' MetaSimpExpr<tag>}]]
+ CaseDecl {CaseDecl}
+.
+
+CaseDecl<> = (. Expression e; .)
+ "case"
+ ( "default"
+ | CalleeParamsNamed
+ )
+
+ BDecl<nullptr>
+.
+
+ /*============================ INTERFACES ===============================*/
Imprt<> =
"import" "raw" '(' string (. root.__rawImports.push_back(Atom<String_t>(t->val).get()); .)
-')' ';'.
+')' '.' .
+
+InterfaceData<> = "interface" '('
+ ( "dfa" ')' InterfaceDFA
+ | "extern-c" ')' InterfaceExternC
+ ).
+
+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 } '}' .
-PassData<> =
-"pass" '(' ident ')' '{' { InDecl } '}' .
-InDecl = (.Operator op; Expression tag;
+InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
-"operator" InAlias<op> ':' '(' (.scheme.setOp(op); .)
+"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)); .)
-';'.
+'.'.
-InAlias<Operator& op> =
+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; .)
-).
+).
+
+
+ /*============================ METAPROGRAMMING ===============================*/
+// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
+// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
+// }.
-TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
-':' { MetaSimpExpr<tag> ['-' TagMod<mod>] (. /*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" ':' (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
-'(' Ident<arg> ':' Domain<typ> (. args.add(arg, typ); .)
-{',' Ident<arg> ':'Domain<typ> (. args.add(arg, typ); .)
+"rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
+'(' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
+{',' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
} ')'
["case" RGuard<guards> {',' RGuard<guards>}]
'{' RBody<args, guards> '}' .
Domain<DomainAnnotation& dom> =
(
"function" (. dom = DomainAnnotation::FUNCTION; .)
| "variable" (. dom = DomainAnnotation::VARIABLE; .)
).
RGuard<RuleGuards& guards>= (. Expression e; .)
MetaExpr<e> (. guards.add(std::move(e)); .).
MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
MetaExpr2<e>
[MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
].
MetaExpr2<Expression& e>=
(
'(' MetaExpr<e> ')'
| MetaSimpExpr<e>
).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
'(' [ CalleeParams<e> ] ')'
| IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
(. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
e.addArg(Expression(Atom<Identifier_t>(i1)));
e.addArg(std::move(e2));
.)
| Ident<i1> (. e = Expression(Atom<Identifier_t>(i1)); .)
).
RBody<const RuleArguments& args, const RuleGuards& guards> =
(. Expression e; std::wstring msg; .)
"warning" MetaExpr<e> ["message" string (. msg = t->val; .)
] (. root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
.
MetaOp< Operator& op> =
implic (. op = Operator::IMPL; .)
.
/*============================ Expressions ===============================*/
-// dublicates CalleeParams
-ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
-'['
-[ Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
-(".." Expr<eTo> (. e.addArg(std::move(eTo)); e.setOp(Operator::LIST_RANGE); .)
- |{',' Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
-} (. e.setOp(Operator::LIST); .)
-) ] ']'.
-
+ExprTyped<Expression&e, TypeAnnotation& typ> = (. Expression tag; .)
+ Expr<e> [tagcolon Type<typ> (. e.bindType(move(typ)); .)
+ {';' MetaSimpExpr<tag> (. e.tags.emplace(tag.getValueString(), move(tag)); .)
+
+ }]
+.
Expr< Expression& e> (. Operator op; Expression e2; .)
= SimExpr< e>
[ RelOp< op>
SimExpr< e2> (. e = Expression(op, {e, e2}); .)
].
SimExpr< Expression& e> (. Operator op; Expression e2; .)
= Term< e>
{ AddOp< op>
Term< e2> (. e = Expression(op, {e, e2});.)
}.
Term< Expression& e> (. Operator op; Expression e2; .)
= Factor< e>
{ MulOp< op>
Factor< e2> (. e = Expression(op, {e, e2}); .)
}.
-Factor< Expression& e> (. std::wstring name;.)
+Factor< Expression& e> (. std::wstring name; TypeAnnotation typ; .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); .)
'(' [CalleeParams<e>] ')'
- |IF (checkIndex()) Ident<name> (. e = Expression(Operator::INDEX, {Atom<Identifier_t>(name)}); .)
- lbrack CalleeParams<e> rbrack
+ |IF (checkIndex()) Ident<name>
+ lbrack CalleeParams<e> rbrack (. e.setOp(Operator::INDEX); e.setValue({Atom<Identifier_t>(name)}); .)
| Ident< name> (. e = Expression(Atom<Identifier_t>(name)); .)
+ | ListLiteral<e> (. /* tuple */.)
+ | StructLiteral<e> (. /* struct */.)
+ | LoopDecl<e, typ, nullptr>
+ | IfDecl<e, typ, nullptr>
+ | SwitchDecl
| number (. e = Expression(Atom<Number_t>(t->val)); .)
+ | string (. e = Expression(Atom<String_t>(t->val)); .)
| '-' Factor< e> (. e = Expression(Operator::NEG, {e}); .)
| '(' Expr<e> ')'
).
+
+StructLiteral<Expression& e> = (. std::wstring key; Expression val; std::list<Atom<Identifier_t>> keys; .)
+ '{' Ident<key> '=' Expr<val> (. keys.push_back(Atom<Identifier_t>(key)); e = Expression(Operator::LIST_NAMED, {val}); .)
+ {',' Ident<key> '=' Expr<val> (.e.addArg(move(val)); keys.push_back(Atom<Identifier_t>(key)); .)
+ } '}' (. e.addBindings(keys.begin(), keys.end()); .)
+ .
+
+ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
+'['
+[ Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
+(".." Expr<eTo> (. e.addArg(std::move(eTo)); e.setOp(Operator::LIST_RANGE); .)
+ |{',' Expr<eFrom> (. e.addArg(std::move(eFrom)); .)
+} (. e.setOp(Operator::LIST); .)
+) ] ']'.
-CalleeParams<Expression& e> = (. Expression e2; .)
- Expr<e2> (. e.addArg(std::move(e2)); .)
- {',' Expr<e2> (. e.addArg(std::move(e2)); .)
+CalleeParams<Expression& e> = (. Expression e2; TypeAnnotation typ; .)
+ ExprTyped<e2, typ> (. e.addArg(std::move(e2)); .)
+ {',' ExprTyped<e2, typ> (. e.addArg(std::move(e2)); .)
}.
+CalleeParamsNamed<> =
+ CalleeParamNamed
+ {',' CalleeParamNamed
+ }.
+
+CalleeParamNamed<> = (. Expression arg; TypeAnnotation argtyp; .)
+ (
+ IF(checkAssignment()) VDecl<new CodeScope()>
+ | ExprTyped<arg, argtyp>
+ ).
+
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| '<' (. op = Operator::LSS; .)
| '>' (. op = Operator::GTR; .)
).
END Xreate.
diff --git a/config/default.json b/config/default.json
new file mode 100644
index 0000000..1cb116b
--- /dev/null
+++ b/config/default.json
@@ -0,0 +1,42 @@
+{
+ "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"
+ }
+ },
+
+ "tests": {
+ "template": "default",
+
+ "templates": {
+ "default": "*-",
+ "types": "Types*-",
+ "containers": "Containers*-",
+ "ast": "AST*",
+ "non-containers": "*-Containers*",
+ "libxml2": "libxml2*",
+ "log": "Logging*"
+ }
+ }
+}
diff --git a/core/containers.lp b/core/containers.lp
index 16b5432..876c7c9 100644
--- a/core/containers.lp
+++ b/core/containers.lp
@@ -1,44 +1,57 @@
%defines
- impl(llvm_array; llvm_const_array; on_the_fly).
- op(seqaccess). op(randaccess).
+ impl(solid; on_the_fly; linked_list).
+ op(seqaccess; 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, llvm_const_array, recommends).
+ relation_op(randaccess, solid, 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).
- 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).
+ -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).
- -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).
-
+ %transfunction implementation:
+ %bind(Vactual, op(Op)) :- var_alias(Vformal, V1); bind(V1, op(Op)); dfa_connection(Vformal, Vactual, arg); op(Op).
- proto_cluster(V0, Vproto) :- cluster_root(V0); cluster_root(Vproto); var_cluster(Vproto, Vp); dfa_connection(V0, Vp, proto).
+ %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).
%optimization
-% #maximize {SCORE, (VAR0, IMPL) : impl_fulfill_cluster(VAR0, IMPL, SCORE)}.
+% #maximize {SCORE, (VAR0, IMPL) : var_impl_fulfill(VAR0, IMPL, SCORE)}.
-#show var_cluster/2.
-#show impl_fulfill_cluster/3.
+#show var_alias/2.
+#show var_impl_fulfill/3.
+#show proto_alias2.
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 16cb9ac..30040d4 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -1,94 +1,141 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
find_package(LLVM REQUIRED CONFIG)
find_package(Qt5Core)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+set(CMAKE_BUILD_TYPE Debug)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
set(SOURCE_FILES
- ./src/ast.cpp ./src/ast-compilation.cpp
+ ./src/ast.cpp
./src/llvmlayer.cpp ./src/clasplayer.cpp
#./src/main.cpp
- ./tests/tests.cpp
+ ./tests/tests.cpp ./tests/testClangAPI.cpp ./tests/testJson.cpp ./tests/testBasic.cpp
+ ./src/utils.cpp
./src/passmanager.cpp
- ./src/pass/abstractpass.cpp
- ./src/pass/dfgpass.cpp
- #./src/pass/cfgpass.cpp ./src/pass/functiontagspass.cpp
- #./src/pass/rulespass.cpp ./src/pass/dfgpass.cpp
+ ./src/pass/abstractpass.cpp ./src/pass/dfgpass.cpp ./src/pass/compilepass.cpp ./src/pass/functiontagspass.cpp
+ #./src/pass/cfgpass.cpp
+ #./src/pass/rulespass.cpp
src/instructions/instr-containers.cpp
src/query/containers.cpp src/attachments.cpp
/opt/potassco/gringo-4.4.0-source/app/shared/src/clingocontrol.cc
/opt/potassco/gringo-4.4.0-source/app/pyclingo/src/clingo_lib.cc
)
set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/)
set(COCO_SOURCE_FILES
${COCO_PATH}/Parser.h
${COCO_PATH}/Scanner.h
${COCO_PATH}/Parser.cpp
${COCO_PATH}/Scanner.cpp
)
set(POTASSCO_PATH "/opt/potassco/gringo-4.4.0-source")
+INCLUDE_DIRECTORIES("/usr/lib/llvm-3.7/include")
+INCLUDE_DIRECTORIES("/usr/include/libxml2")
+INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES(${COCO_PATH} ./src)
INCLUDE_DIRECTORIES(${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/app/shared/include
${POTASSCO_PATH}/app/pyclingo/src
${POTASSCO_PATH}/libprogram_opts
)
-
+
+include_directories(${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/)
+
#execute_process(COMMAND ${COCO_PATH}/gen-xreate WORKING_DIRECTORY OUTPUT_VARIABLE COCO_OUTPUT)
message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT})
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
-add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} )
+add_executable(xreate ${SOURCE_FILES} ${COCO_SOURCE_FILES} tests/testLibXml2.h tests/testLibXml2.cpp src/ExternLayer.cpp src/ExternLayer.h)
set(COCO_TARGET cocoTarget)
add_custom_target(${COCO_TARGET}
WORKING_DIRECTORY ${COCO_PATH}
)
add_custom_command(TARGET ${COCO_TARGET}
PRE_BUILD
COMMAND ${COCO_PATH}/gen-xreate
WORKING_DIRECTORY ${COCO_PATH}
)
-#add_dependencies(${PROJECT_NAME} ${COCO_TARGET})
+add_custom_target (coverage
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+
+message(STATUS "BINARY DIR" ${CMAKE_BINARY_DIR})
-llvm_map_components_to_libnames(llvm_libs support core irreader)
+#add_dependencies(${PROJECT_NAME} coverageTarget)
+
+llvm_map_components_to_libnames(llvm_libs support core irreader all native nativecodegen)
message(STATUS "LLVM LIBS: " ${llvm_libs})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
#find_library(LIBCLASP_LIBRARY_GRINGO NAMES gringo
# HINTS ${LIBCLASP_PATH})
#find_library(LIBCLASP_LIBRARY_CLASP NAMES clasp
# HINTS ${LIBCLASP_PATH})
set(LIBCLASP_LIBS
${LIBCLASP_PATH}/libclasp.a
${LIBCLASP_PATH}/libgringo.a
${LIBCLASP_PATH}/libprogram_opts.a
)
+#set(LIBCLANG_PATH "/usr/lib/llvm-3.7/lib/")
+#set(LIBCLANG_LIBS
+##/usr/lib/llvm-3.7/lib/libclangToolingCore.a
+#/usr/lib/llvm-3.7/lib/libclangTooling.a
+#)
+
+file(GLOB_RECURSE LIBCLANG_LIBS2 /usr/lib/llvm-3.7/lib/*.a)
+
+set(LIBCLANG_LIBS
+/usr/lib/llvm-3.7/lib/libclangParse.a
+/usr/lib/llvm-3.7/lib/libclangFormat.a
+${LIBCLANG_LIBS2}
+${LIBCLANG_LIBS2}
+/usr/lib/llvm-3.7/lib/libclangParse.a
+/usr/lib/llvm-3.7/lib/libclangFormat.a
+)
+
+message(STATUS "ALL LIBS: " ${LIBCLANG_LIBS})
+
+
message(STATUS ${LIBCLASP_LIBS})
-target_link_libraries(xreate ${llvm_libs} pthread Qt5::Core ${LIBCLASP_LIBS})
+
add_definitions(-DWITH_THREADS=0)
+
+FUNCTION(PREPEND var prefix)
+ SET(listVar "")
+ FOREACH(f ${ARGN})
+ LIST(APPEND listVar "${prefix}/${f}")
+ ENDFOREACH(f)
+ SET(${var} "${listVar}" PARENT_SCOPE)
+ENDFUNCTION(PREPEND)
+
+
+find_package(GTest REQUIRED)
+INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall -fprofile-arcs -ftest-coverage -O0")
+
+target_link_libraries(xreate ${GTEST_LIBRARIES} ${llvm_libs} ${LIBCLANG_LIBS} pthread xml2 Qt5::Core ${LIBCLASP_LIBS} gcov)
diff --git a/cpp/code-coverage.sh b/cpp/code-coverage.sh
new file mode 100755
index 0000000..a1ee2de
--- /dev/null
+++ b/cpp/code-coverage.sh
@@ -0,0 +1,2 @@
+lcov --capture --directory ./ --output-file coverage.info
+genhtml coverage.info --output-directory coverage-report
diff --git a/cpp/src/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
new file mode 100644
index 0000000..1b95b7e
--- /dev/null
+++ b/cpp/src/ExternLayer.cpp
@@ -0,0 +1,274 @@
+//
+// Created by pgess on 4/21/15.
+//
+
+#include "ExternLayer.h"
+
+#include "QStringList"
+#include <cstdio>
+#include <iostream>
+#include "clang/Tooling/Tooling.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/TargetInfo.h"
+#include <llvm/Support/DynamicLibrary.h>
+
+using namespace xreate;
+using namespace std;
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::tooling;
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+
+class FinderCallbackTypeDecl : public MatchFinder::MatchCallback {
+public :
+ QualType typeResult;
+
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
+ typeResult = decl->getUnderlyingType();
+ }
+ }
+};
+
+class FinderCallbackFunction : public MatchFinder::MatchCallback {
+public :
+ QualType typeResult;
+
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
+ typeResult = decl->getType();
+ }
+ }
+};
+
+void
+ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package)
+{
+ __dictLibraries.emplace(name.get(), package.get());
+}
+
+void
+ExternData::addIncludeDecl(Expression&& e)
+{
+ assert(e.op == Operator::LIST_NAMED);
+
+ //TODO implement Expression parsing(Array of Expr as vector<string>);
+ int indexLib, indexHeaders;
+ for(size_t i=0, size=e.operands.size(); i<size; ++i)
+ {
+ std::string library = e.bindings.at(i);
+ assert(__dictLibraries.count(library));
+ std::string package = __dictLibraries.at(library);
+
+ Expression listHeaders = e.operands.at(i);
+ assert(listHeaders.op == Operator::LIST);
+
+ std::vector<std::string> headers;
+ std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
+ [](const Expression& o){
+ assert(o.__state == Expression::STRING);
+ return o.getValueString();
+ });
+
+ entries.emplace_back(ExternEntry{package, std::move(headers)});
+ }
+}
+
+void
+ExternLayer::addExternalData(const std::vector<ExternEntry>& data){
+ entries.insert(entries.end(), data.begin(), data.end());
+}
+
+ExternLayer::ExternLayer(LLVMLayer *llvm): __llvm(llvm), __datalayout(llvm->module)
+{}
+
+
+std::vector<string>
+ExternLayer::fetchPackageFlags(const ExternEntry& entry){
+ std::vector<string> args;
+ FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
+ size_t linesize=0;
+ char* linebuf=0;
+ ssize_t linelen=0;
+ while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
+ if (linebuf[0]=='\n') continue;
+ if (linebuf[linelen-1 ] == ' ')
+ linebuf[linelen-1] = 0;
+
+ llvm::outs() << '<' << linebuf << "> ";
+ args.push_back(linebuf);
+
+ free(linebuf);
+ linebuf = 0;
+ }
+ pclose(flags);
+ return (args);
+}
+
+std::vector<string>
+ExternLayer::fetchPackageLibs(const ExternEntry& entry){
+ std::vector<string> libs;
+
+ FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
+ size_t linesize=0;
+ char* linebuf=0;
+ ssize_t linelen=0;
+ while ((linelen=getdelim(&linebuf, &linesize, ' ', flags))>0) {
+ if (linebuf[0]=='\n') continue;
+ if (linebuf[linelen-1 ] == ' ')
+ linebuf[linelen-1] = 0;
+
+ llvm::outs() << '<' << linebuf << "> ";
+ libs.push_back(linebuf);
+
+ free(linebuf);
+ linebuf = 0;
+ }
+ pclose(flags);
+ return (libs);
+}
+
+void
+ExternLayer::loadLibraries(vector<string>&& libs){
+ string msgErr;
+ for (const string& lib: libs) {
+ if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(lib.c_str(), &msgErr)){
+ llvm::errs()<<"\n"<<msgErr<<"\n";
+ }
+ }
+}
+
+void
+ExternLayer::init(const AST* root) {
+ addExternalData(root->__externdata);
+
+ QStringList code;
+ std::vector<string> args{
+ "-I/usr/local/include"
+ ,"-I/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0/include"
+ ,"-I/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include"
+ ,"-I/usr/include/x86_64-linux-gnu"
+ ,"-I/usr/include"
+ };
+
+ std::vector<string> libs;
+
+ for(const ExternEntry& entry: entries)
+ {
+ llvm::outs()<<"[ExternC] Processing package: "<< entry.package << "\n";
+ llvm::outs()<<"[ExternC] args: ";
+
+ vector<string>&& args2 = fetchPackageFlags(entry);
+ args.insert(args.end(), args2.begin(), args2.end());
+ for(const string arg: args2) {
+ llvm::outs()<< "<" << arg << "> ";
+ }
+
+ llvm::outs()<<"\n[ExternC] libs: ";
+ args2 = fetchPackageLibs(entry);
+ for(const string arg: args2) {
+ llvm::outs()<< "<" << arg << "> ";
+ }
+ libs.insert(libs.end(), args2.begin(), args2.end());
+
+
+ llvm::outs()<<"\n[ExternC] headers: ";
+ std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
+ [](const string header ) {
+ QString line = QString("#include \"%1\"").arg(header.c_str());
+ llvm::outs()<< "<" << line.toStdString() << "> ";
+
+ return line;
+ });
+
+ llvm::outs() << '\n';
+ }
+
+
+ loadLibraries(move(libs));
+ ast = buildASTFromCodeWithArgs(code.join('\n').toStdString(), args);
+ __cgo.reset(new CodeGenOptions);
+ __datalayout = llvm::DataLayout(ast->getASTContext().getTargetInfo().getTargetDescription());
+ __cgm.reset(new CodeGen::CodeGenModule(ast->getASTContext(), *__cgo, *__llvm->module, __datalayout, ast->getASTContext().getDiagnostics()));
+};
+
+
+
+bool
+ExternLayer::isPointer(const clang::QualType &t) {
+ const clang::Type * tInfo = t.getTypePtr();
+ assert(tInfo);
+
+ return tInfo->isAnyPointerType();
+}
+
+llvm::Type*
+ExternLayer::toLLVMType(const clang::QualType& t){
+ return __cgm->getTypes().ConvertType(t);
+}
+
+std::vector<std::string>
+ExternLayer::getStructFields(const clang::QualType& ty)
+{
+ clang::QualType t = ty;
+ if (isPointer(ty)){
+ const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
+ t = tPtr->getPointeeType();
+ }
+
+ assert(t.getTypePtr()->isRecordType());
+
+ const RecordType *record = t->getAsStructureType();
+ assert(record);
+
+ std::vector<std::string> result;
+ //FieldDecl* field: record->getDecl()->fields()
+ for (auto i=record->getDecl()->field_begin(); i!= record->getDecl()->field_end(); ++i){
+ result.push_back(i->getName());
+ }
+
+ return result;
+}
+
+clang::QualType
+ExternLayer::lookupType(const std::string& id){
+ MatchFinder finder;
+ FinderCallbackTypeDecl callbackTypeDecl;
+ auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
+
+ finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
+ finder.matchAST(ast->getASTContext());
+
+ assert(! callbackTypeDecl.typeResult.isNull());
+ return callbackTypeDecl.typeResult;
+}
+
+
+llvm::Function*
+ExternLayer::lookupFunction(const std::string& name){
+ if (__functions.count(name)){
+ return __functions.at(name);
+ }
+
+ MatchFinder finder;
+ FinderCallbackFunction callback;
+ auto matcher = functionDecl(hasName(name)).bind("function");
+
+ finder.addMatcher(matcher, &callback);
+ finder.matchAST(ast->getASTContext());
+
+ assert(! callback.typeResult.isNull());
+ const QualType& tyFuncQual = callback.typeResult;
+ llvm::Type *tyRaw = __cgm->getTypes().ConvertType(tyFuncQual);
+ llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
+
+ llvm::Function* function = llvm::Function::Create(tyRawFunc, llvm::GlobalValue::ExternalLinkage, name, __llvm->module);
+
+ __functions.emplace(name, function);
+ return function;
+}
diff --git a/cpp/src/ExternLayer.h b/cpp/src/ExternLayer.h
new file mode 100644
index 0000000..cc2a18f
--- /dev/null
+++ b/cpp/src/ExternLayer.h
@@ -0,0 +1,55 @@
+//
+// Created by pgess on 4/21/15.
+//
+
+#ifndef XREATE_EXTERNLAYER_H
+#define XREATE_EXTERNLAYER_H
+
+#include "llvmlayer.h"
+#include <vector>
+#include <string>
+#include <map>
+#include "ast.h"
+#include "clang/AST/ASTContext.h"
+#include "/private/prg/vendors/clang/lib/CodeGen/CodeGenModule.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+namespace xreate {
+ struct ExternData {
+ void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
+ void addIncludeDecl(Expression&& e);
+
+ std::vector<ExternEntry> entries;
+ std::map<std::string, std::string> __dictLibraries;
+ };
+
+ class ExternLayer {
+ public:
+ ExternLayer(LLVMLayer* llvm);
+
+ llvm::Function* lookupFunction(const std::string& name);
+ clang::QualType lookupType(const std::string& id);
+ std::vector<std::string> getStructFields(const clang::QualType& ty);
+
+ llvm::Type* toLLVMType(const clang::QualType& t);
+ bool isPointer(const clang::QualType& t);
+
+ void init(const AST* root);
+ static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
+ static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
+ private:
+
+ std::unique_ptr<clang::ASTUnit> ast;
+ std::unique_ptr<clang::CodeGen::CodeGenModule> __cgm;
+ std::unique_ptr<clang::CodeGenOptions> __cgo;
+ llvm::DataLayout __datalayout;
+ LLVMLayer* __llvm;
+ std::vector<ExternEntry> entries;
+ std::map<std::string, llvm::Function*> __functions;
+
+ void addExternalData(const std::vector<ExternEntry>& data);
+ void loadLibraries(std::vector<std::string>&& libs);
+ };
+}
+#endif //XREATE_EXTERNLAYER_H
diff --git a/cpp/src/ast-compilation.cpp b/cpp/src/ast-compilation.cpp
deleted file mode 100644
index 1bf4c97..0000000
--- a/cpp/src/ast-compilation.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <ast.h>
-#include <iostream>
-#include "query/containers.h"
-#include "instructions/instr-containers.h"
-
-using namespace xreate;
-using namespace std;
-
- llvm::Value *
- CodeScope::compileExpression(const Expression &expr, LLVMLayer &l, std::string hintRetVar) {
- #define VARNAME(x) (hintRetVar.empty()? x: hintRetVar)
- llvm::Value *left;
- llvm::Value *right;
-
-
- switch (expr.op) {
- case Operator::ADD:
- case Operator::SUB:
- case Operator::MUL:
- case Operator::DIV:
- case Operator::EQU:
- case Operator::LSS:
- case Operator::GTR:
- assert(expr.__state == Expression::COMPOUND);
- assert(expr.operands.size() == 2);
-
- left = compileExpression(expr.operands[0], l);
- right = compileExpression(expr.operands[1], l);
- break;
-
- default:;
- }
-
- switch (expr.op) {
- case Operator::ADD:
- return l.builder.CreateAdd(left, right, VARNAME("tmp_add"));
- break;
-
- case Operator::SUB:
- return l.builder.CreateSub(left, right, VARNAME("tmp_sub"));
- break;
-
- case Operator::MUL:
- return l.builder.CreateMul(left, right, VARNAME("tmp_mul"));
- break;
-
- case Operator::DIV:
- return l.builder.CreateSDiv(left, right, VARNAME("tmp_div"));
- break;
-
- case Operator::EQU:
- left->dump();
- right->dump();
- return l.builder.CreateICmpEQ(left, right, VARNAME("tmp_equ"));
- break;
-
- case Operator::LSS:
- return l.builder.CreateICmpSLT(left, right, VARNAME("tmp_lss"));
- break;
-
- case Operator::GTR:
- return l.builder.CreateICmpSGT(left, right, VARNAME("tmp_gtr"));
- break;
-
- case Operator::NEG:
- left = compileExpression(expr.operands[0], l);
- return l.builder.CreateNeg(left, VARNAME("tmp_neg"));
- break;
-
- case Operator::CALL: {
- assert(expr.__state == Expression::COMPOUND);
-
- const std::string &fname = expr.__valueS;
-
- ManagedFnPtr calleeFunc = l.ast->findFunction(fname);
- assert(calleeFunc.isValid());
-
- llvm::Function *callee = calleeFunc->__raw;
-
- std::vector<llvm::Value *> args;
- args.reserve(expr.operands.size() - 1);
-
- std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
- [&l, this](const Expression &operand) {
- return compileExpression(operand, l);
- }
- );
-
- return l.builder.CreateCall(callee, args, VARNAME("tmp_call"));
- }
-
- case Operator::LIST:
- {
- return containers::Instructions(this, &l).compileConstantArray(expr, VARNAME("list"));
- };
-
- case Operator::LIST_RANGE:
- {
- assert(false); //no compilation phase for a range list
- // return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
- };
-
-
-
- case Operator::MAP:
- {
- assert(expr.blocks.size());
- return containers::Instructions(this, &l).compileMapArray(expr, VARNAME("map"));
- };
-
- case Operator::FOLD:
- {
- return containers::Instructions(this, &l).compileFold(expr, VARNAME("fold"));
- };
-
- case Operator::INDEX:
- {
- assert(expr.operands.size());
- const std::string &ident = expr.operands.begin()->getValueString();
- Symbol s = findSymbol(ident, l, true);
-
- std::vector<llvm::Value*> indexes;
- std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
- [this, &l] (const Expression& op){return compileExpression(op, l);}
- );
-
- return containers::Instructions(this, &l).compileIndex(s, indexes, VARNAME(string("el_") + ident));
- };
-
-
- case Operator::NONE:
- assert(expr.__state != Expression::COMPOUND);
-
- switch (expr.__state) {
- case Expression::IDENT: {
- const std::string &vname = expr.__valueS;
- const Symbol& var = findSymbol(vname, l, true);
- return var.scope->__rawVars.at(var.identifier);
- }
-
- case Expression::NUMBER:
- int literal = expr.__valueD;
- return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
- };
-
- break;
-
- }
-
- assert(false);
- return 0;
- }
-
- llvm::Value *
- CodeScope::compile(LLVMLayer &l, const std::string& hintBlockName) {
- if (!hintBlockName.empty()) {
- llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockName, l.context.function);
- l.builder.SetInsertPoint(block);
- }
-
- return compileExpression(__body, l);
- }
-
- llvm::Function *
- Function::compile(LLVMLayer &l) {
- std::vector<llvm::Type *> types;
- std::transform(__entry->__args.begin(), __entry->__args.end(), std::inserter(types, types.end()),
- [this](const std::string &arg)->llvm::Type* {
- assert(__entry->__vartable.count(arg));
- VID argid = __entry->__vartable.at(arg);
- assert(__entry->__definitions.count(argid));
- return __entry->__definitions.at(argid).toLLVMType();
- });
-
- llvm::FunctionType *ft = llvm::FunctionType::get(__entry->__definitions[0].toLLVMType(), types, false);
- __raw = llvm::cast<llvm::Function>(l.module->getOrInsertFunction(__name, ft));
-
- llvm::Function::arg_iterator fargsI = __raw->arg_begin();
- for (std::string &arg : __entry->__args) {
- VID argid = __entry->__vartable[arg];
-
- __entry->__rawVars[argid] = fargsI;
- fargsI->setName(arg);
- ++fargsI;
- }
-
- l.context.function = __raw;
- const std::string blockName = "entry";
- l.builder.CreateRet(__entry->compile(l, blockName));
- l.context.function = nullptr;
- l.moveToGarbage(ft);
-
- return __raw;
- };
-
- void
- AST::compile(LLVMLayer &layer) {
- layer.ast = this;
- layer.module = new llvm::Module(getModuleName(), llvm::getGlobalContext());
-
- for (Function* f: __functions) {
- llvm::Function *rawf = f->compile(layer);
- }
- }
\ No newline at end of file
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 9051e77..6f7b723 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,456 +1,637 @@
#include "ast.h"
+#include "ExternLayer.h"
#include <stdexcept>
#include <iostream>
#include <QString>
#include <clasplayer.h>
using namespace std;
namespace xreate{
+class TypesResolver {
+private:
+ const AST* ast;
+ std::map<std::string, TypeAnnotation> scope;
+ std::map<TypeAnnotation, int> signatures;
+
+
+ ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()){
+ return TypesResolver(ast, scope, signatures)(t, args);
+ }
+
+ std::vector<TypeAnnotation>
+ expandOperands(const std::vector<TypeAnnotation>& operands) {
+ std::vector<TypeAnnotation> pack;
+
+ pack.reserve(operands.size());
+ std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
+ [this](const TypeAnnotation& t){
+ return expandType(t);
+ });
+
+ return pack;
+ }
+
+public:
+ TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
+ std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
+ : ast(root), scope(scopeOuter), signatures(signaturesOuter) {
+ }
+
+
+
+ ExpandedType
+ operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>())
+ {
+ assert(args.size() == t.bindings.size()); // invalid number of arguments
+ for (int i=0; i<args.size(); ++i)
+ {
+ scope[t.bindings.at(i)] = args.at(i);
+ }
+
+ switch (t.__operator)
+ {
+ case TypeOperator::ARRAY:
+ {
+ assert(t.__operands.size()==1);
+
+ Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
+ return ExpandedType(TypeAnnotation(tag_array, elTy, t.__size));
+ }
+
+ case TypeOperator::STRUCT:
+ {
+ assert(t.__operands.size());
+
+ std::vector<TypeAnnotation>&& pack = expandOperands(t.__operands);
+ auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack));
+ tnew.fields = t.fields;
+
+ return ExpandedType(move(tnew));
+ };
+
+ case TypeOperator::CALL:
+ {
+ std::string alias = t.__valueCustom;
+
+ //find in local scope:
+ TypeAnnotation ty;
+ if (scope.count(alias)) {
+ ty = scope.at(alias);
+
+ } else if (ast->__indexTypeAliases.count(alias)){
+ ty = ast->__indexTypeAliases.at(alias);
+
+ } else {
+ assert(false && "Undefined or external type");
+ }
+
+ std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
+ TypeAnnotation signature(TypeOperator::CALL, move(operands));
+ signature.__valueCustom = alias;
+
+ if (signatures.count(signature)) {
+ auto link = TypeAnnotation(TypeOperator::LINK, {});
+ link.conjuctionId = signatures.at(signature);
+
+ return ExpandedType(move(link));
+ }
+
+ int cid = signatures.size();
+ signatures[signature] = cid;
+ TypeAnnotation tyResult = expandType(ty, operands);
+ tyResult.conjuctionId = cid;
+
+ return ExpandedType(move(tyResult));
+ };
+
+ case TypeOperator::CUSTOM:
+ {
+ std::string alias = t.__valueCustom;
+
+ /*
+ if (signatures.count(alias)) {
+ return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
+ }
+ signatures[alias].emplace(t);
+ */
+
+ //find in local scope:
+ if (scope.count(alias))
+ {
+ return expandType(scope.at(alias));
+ }
+
+ // find in general scope:
+ if(ast->__indexTypeAliases.count(alias)) {
+ return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
+ }
+
+ //if type is unknown keep it as is.
+ return ExpandedType(TypeAnnotation(t));
+ };
+
+ case TypeOperator::ACCESS:
+ {
+ std::string alias = t.__valueCustom;
+ ExpandedType tyAlias= ExpandedType(TypeAnnotation());
+
+ //find in local scope:
+ if (scope.count(alias)) {
+ tyAlias = expandType(scope.at(alias));
+
+ //find in global scope:
+ } else if((ast->__indexTypeAliases.count(alias))) {
+ tyAlias = expandType(ast->__indexTypeAliases.at(alias));
+
+ } else {
+ assert(false && "Undefined or external type");
+ }
+
+ assert(tyAlias->__operator == TypeOperator::STRUCT);
+
+ for (const string& field: t.fields){
+ auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
+ assert(fieldIt != tyAlias->fields.end() && "unknown field");
+
+ int fieldId = fieldIt - tyAlias->fields.begin();
+ tyAlias = expandType(tyAlias->__operands.at(fieldId));
+ }
+
+ return tyAlias;
+ }
+
+ case TypeOperator::TUPLE: {
+ assert(t.__operands.size());
+
+ std::vector<TypeAnnotation> pack;
+ pack.reserve(t.__operands.size());
+
+ std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()),
+ [this](const TypeAnnotation& t){
+ return expandType(t);
+ });
+
+ return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack)));
+ }
+
+ case TypeOperator::NONE: {
+ return ExpandedType(TypeAnnotation(t));
+ }
+
+ default:
+ assert(false);
+ }
+
+ assert(false);
+ return ExpandedType(TypeAnnotation());
+ }
+};
+
TypeAnnotation::TypeAnnotation()
{
}
TypeAnnotation::TypeAnnotation(const Atom<Type_t> &typ)
: __value(typ.get())
{
;
}
TypeAnnotation::TypeAnnotation (TypePrimitive typ)
: __value(typ)
{}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands)
{
}
-TypeAnnotation::TypeAnnotation (llvm_array_tag, TypePrimitive typ, int size)
- :TypeAnnotation(TypeOperator::LIST, {typ})
-{
- __size=size;
-}
-/*
-TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
+TypeAnnotation::TypeAnnotation (TypeOperator op, std::vector<TypeAnnotation>&& operands)
+ : __operator(op), __operands(operands)
{}
-*/
-llvm::Type*
-TypeAnnotation::toLLVMType()
+
+TypeAnnotation::TypeAnnotation (llvm_array_tag, TypeAnnotation typ, int size)
+ :TypeAnnotation(TypeOperator::ARRAY, {typ})
{
- switch (__operator)
- {
- case TypeOperator::LIST:
- {
- assert(__operands.size());
- TypeAnnotation elTy = __operands.at(0);
+ __size=size;
+}
- return llvm::ArrayType::get(elTy.toLLVMType(), __size);
- }
+bool
+TypeAnnotation::operator< (const TypeAnnotation& t) const{
+ if (__operator != t.__operator) return __operator < t.__operator;
- case TypeOperator::NONE: {
- switch (__value) {
- case TypePrimitive::Bool:
- return llvm::Type::getInt1Ty(llvm::getGlobalContext());
+ if (__operator == TypeOperator::NONE)
+ return __value < t.__value;
- case TypePrimitive::Int:
- case TypePrimitive::i32:
- case TypePrimitive::Num:
- return llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS){
+ if (__valueCustom != t.__valueCustom)
+ return __valueCustom < t.__valueCustom;
+ }
- case TypePrimitive::Float:
- return llvm::Type::getDoubleTy(llvm::getGlobalContext());
+ return __operands < t.__operands;
+}
- default:
- assert(false);
- }
- }
+/*
+TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
+{}
+*/
- default:
- assert(false);
- }
+void
+TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params)
+{
+ bindings.reserve(params.size());
- assert(false);
- return nullptr;
+ std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
+ [](const Atom<Identifier_t>& ident){return ident.get(); });
}
-
-
Expression::Expression(const Atom<Number_t>& number)
: __state(NUMBER), op(Operator::NONE), __valueD(number.get())
{
}
+Expression::Expression(const Atom<String_t>& a)
+ : __state(STRING), op(Operator::NONE), __valueS(a.get())
+{
+}
+
Expression::Expression(const Atom<Identifier_t> &ident)
: __state(IDENT), op(Operator::NONE), __valueS(ident.get())
{
+
+ if (ident.get() == "null") {
+ __state = NONE;
+ }
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: __state(COMPOUND), op(oprt)
{
if (op == Operator::CALL)
{
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
+
+ operands.insert(operands.end(), params.begin()+1, params.end());
return;
}
- operands.insert(operands.end(), params);
+ operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt)
{
op = oprt;
switch (op)
{
case Operator::NONE:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg)
{
operands.push_back(arg);
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params)
{
- std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
- [] (const Atom<Identifier_t> atom){
- return atom.get();
- });
+ addBindings(params.begin(), params.end());
+}
+
+void
+Expression::bindType(TypeAnnotation&& t)
+{
+ type = t;
}
void
Expression::addBlock(ManagedScpPtr scope)
{
- blocks.push_back(scope);
+ blocks.push_back(scope.operator ->());
}
const std::vector<Expression>&
Expression::getOperands() const
{
return operands;
}
double
Expression::getValueDouble() const
{
return __valueD;
}
const std::string&
Expression::getValueString() const
{
return __valueS;
}
+void
+Expression::setValue(const Atom<Identifier_t>&& v){
+ __valueS = v.get();
+}
+bool
+Expression::isNone() const{
+ return (op == Operator::NONE && __state == NONE);
+}
+bool
+Expression::isValid() const{
+ return (__state != INVALID);
+}
Expression::Expression()
: op(Operator::NONE), __state(INVALID)
{}
AST::AST()
{
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
+void
+AST::addExternData(ExternData &&data) {
+ __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
+}
+
void
AST::add(Function* f)
{
__functions.push_back(f);
__indexFunctions[f->getName()] = __functions.size()-1;
}
void
AST::add(MetaRuleAbstract *r)
{
__rules.push_back(r);
}
+void
+AST::add(TypeAnnotation&& t, Atom<Identifier_t>&& alias){
+ __indexTypeAliases.emplace(alias.get(), t);
+}
+
ManagedScpPtr
AST::add(CodeScope* scope)
{
this->__scopes.push_back(scope);
return ManagedScpPtr(this->__scopes.size()-1, &this->__scopes);
}
std::string
AST::getModuleName()
{
const std::string name = "moduleTest";
return name;
}
ManagedPtr<Function>
AST::findFunction(const std::string& name)
{
- assert (__indexFunctions.count(name));
+ if (! __indexFunctions.count(name)) {
+ return ManagedFnPtr::Invalid();
+ }
return ManagedPtr<Function>(__indexFunctions.at(name), &__functions);
}
-void
-AST::run(LLVMLayer &l)
+ template<>
+ManagedPtr<Function>
+AST::begin<Function>()
+{return ManagedPtr<Function>(0, &this->__functions);}
+
+template<>
+ManagedPtr<CodeScope>
+AST::begin<CodeScope>()
+{return ManagedPtr<CodeScope>(0, &this->__scopes);}
+
+template<>
+ManagedPtr<MetaRuleAbstract>
+AST::begin<MetaRuleAbstract>()
+{return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);}
+
+
+Expanded<TypeAnnotation>
+AST::expandType(const TypeAnnotation &t) const
{
- llvm::PassManager<llvm::Module> PM;
- PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
- PM.run(*l.module);
+ return TypesResolver(this)(t);
}
- template<>
- ManagedPtr<Function>
- AST::begin<Function>()
- {return ManagedPtr<Function>(0, &this->__functions);}
+Expanded<TypeAnnotation>
+AST::findType(const std::string& name){
+ // find in general scope:
+ if(__indexTypeAliases.count(name))
+ return expandType(__indexTypeAliases.at(name));
- template<>
- ManagedPtr<CodeScope>
- AST::begin<CodeScope>()
- {return ManagedPtr<CodeScope>(0, &this->__scopes);}
-
- template<>
- ManagedPtr<MetaRuleAbstract>
- AST::begin<MetaRuleAbstract>()
- {return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);}
+ //if type is unknown keep it as is.
+ TypeAnnotation t(TypeOperator::CUSTOM, {});
+ t.__valueCustom = name;
+ return ExpandedType(move(t));
+}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0))
{
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod)
{
__tags.emplace_back(tag, mod);
}
const std::vector<Tag>&
Function::getAnnotations() const
{
return __tags;
}
CodeScope*
Function::getEntryScope() const
{
return __entry;
}
void
CodeScope::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
{
VID id = registerVar(std::move(const_cast<std::string&>(name.get())), std::move(typ));
__args.push_back(name.get());
}
;
void
Function::addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ)
{
__entry->addArg(move(name), move(typ));
}
void
Function::setReturnType(const TypeAnnotation &rtyp)
{
__entry->__definitions[0] = rtyp;
}
const std::string&
Function::getName() const
{
return __name;
}
CodeScope::CodeScope(CodeScope* parent)
:__parent(parent)
{}
CodeScope::~CodeScope()
{}
VID
CodeScope::registerVar(std::string&& name, TypeAnnotation &&typ)
{
__vartable[name] = ++__vCounter;
__definitions[__vCounter] = typ;
return __vCounter;
}
-void
-CodeScope::bindArg(llvm::Value* var, std::string&& name)
-{
- assert(__vartable.count(name));
- VID id = __vartable.at(name);
- __rawVars[id] = var;
-}
-
void
CodeScope::addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body)
{
VID id = registerVar(std::move(const_cast<string&>(name.get())), move(typ));
__declarations[id] = body;
}
void
CodeScope::setBody(const Expression &body)
{
__body = body;
}
TypeAnnotation&
CodeScope::findDefinition(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
- self->__definitions[symbol.identifier];
+ assert(self->__definitions.count(symbol.identifier));
+ return self->__definitions[symbol.identifier];
}
Symbol
-CodeScope::findSymbol(const std::string &name, LLVMLayer &l, bool forceCompile)
+CodeScope::findSymbol(const std::string &name)
{
//search var in current block
if (__vartable.count(name))
{
VID vId = __vartable.at(name);
Symbol result{vId, this};
-
- 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] = compileExpression(e, l, name);
return result;
}
//search in parent scope
if (__parent)
{
- return __parent->findSymbol(name, l);
+ return __parent->findSymbol(name);
}
//exception: Ident not found
assert(false);
}
+
+
bool
CodeScope:: hasDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
return (self->__declarations.count(symbol.identifier));
}
-llvm::Value*
-CodeScope::compileExpression(const Symbol& s, LLVMLayer& l, std::string hintRetVar)
-{
- CodeScope* self = s.scope;
-
- if (self->__rawVars.count(s.identifier))
- {
- return self->__rawVars[s.identifier];
- }
-
- return self->__rawVars[s.identifier] = self->compileExpression(findDeclaration(s), l, hintRetVar);
-}
-
const Expression&
CodeScope::findDeclaration(const Symbol& symbol)
{
CodeScope* self = symbol.scope;
if (! self->__declarations.count(symbol.identifier))
{
// no declaration exists
assert(false);
}
return self->__declarations[symbol.identifier];
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ)
{
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e)
{
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards))
{}
MetaRuleAbstract::~MetaRuleAbstract(){}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __condition(condition), __message(message.get())
{}
RuleWarning::~RuleWarning(){}
void
RuleWarning::compile(ClaspLayer& layer)
{
layer.addRuleWarning(*this);
}
bool operator< (const Symbol& s1, const Symbol& s2)
{
return (s1.scope < s2.scope) || (s1.scope==s2.scope && s1.identifier<s2.identifier);
}
bool operator== (const Symbol& s1, const Symbol& s2)
{
return (s1.scope == s2.scope) && (s1.identifier==s2.identifier);
}
}
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index c2862fb..769b295 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,432 +1,511 @@
#ifndef AST_H
#define AST_H
#include <vector>
#include <stdlib.h>
#include <string>
-#include "llvmlayer.h"
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "attachments.h"
+#include "utils.h"
+#include <algorithm>
+
+namespace llvm{
+ class Value;
+}
namespace xreate {
struct String_t{};
struct Identifier_t {};
struct Number_t {};
struct Type_t {};
template<typename A>
class Atom {};
template<> class Atom<Identifier_t>
{
public:
Atom(const std::wstring& value)
{
char buffer[32];
wcstombs(buffer, value.c_str(), 32);
__value = buffer;
}
Atom(std::string && name): __value(name) {}
const std::string& get() const{return __value; }
private:
std::string __value;
};
template<> class Atom<Number_t>
{
public:
Atom(wchar_t* value)
{
__value = wcstol(value, 0, 10);
}
Atom(int value)
: __value(value)
{}
double get()const {return __value; }
private:
double __value;
};
template<> class Atom<String_t>
{
public:
Atom(const std::wstring& value)
: __value(++value.begin(), --value.end())
{}
const std::string& get() const {return __value; }
private:
std::string __value;
};
-enum class TypePrimitive {Bool, Int, Float, Num, String, i32};
+enum class TypePrimitive {Bool, Int, Float, Num, String, I32, I8};
template<> class Atom<Type_t>
{
public:
Atom(wchar_t* value)
{
char buffer_[32];
wcstombs(buffer_, value, 32);
std::string buffer(buffer_);
if (buffer=="bool"){
__value = TypePrimitive ::Bool;
} else if (buffer=="int") {
__value = TypePrimitive::Int;
} else if (buffer=="float") {
__value = TypePrimitive::Float;
} else if (buffer=="num") {
__value = TypePrimitive::Num;
} else if (buffer=="string") {
__value = TypePrimitive::String;
}
}
Atom()
{
}
TypePrimitive get() const
{
return __value;
}
private:
TypePrimitive __value;
};
typedef Atom<Type_t> TypeAtom;
-enum class TypeOperator{NONE, LIST, STRUCT};
+enum class TypeOperator{NONE, CALL, CUSTOM, ARRAY, TUPLE, STRUCT, ACCESS, LINK};
struct llvm_array_tag {}; struct struct_tag{};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
class TypeAnnotation
{
public:
TypeAnnotation();
TypeAnnotation (const Atom<Type_t>& typ);
TypeAnnotation (TypePrimitive typ);
- TypeAnnotation (llvm_array_tag, TypePrimitive typ, int size);
+ TypeAnnotation (llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation (TypeOperator op, std::initializer_list<TypeAnnotation> operands);
+ TypeAnnotation (TypeOperator op, std::vector<TypeAnnotation>&& operands);
+ void addBindings(std::vector<Atom<Identifier_t>>&& params);
+ bool operator< (const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
- llvm::Type* toLLVMType();
- TypePrimitive __value;
TypeOperator __operator = TypeOperator::NONE;
+
std::vector<TypeAnnotation> __operands;
- int __size = 0;
-private:
+ TypePrimitive __value;
+ std::string __valueCustom;
+ int conjuctionId=-1; //conjunction point id (relevant for recursive types)
+ uint64_t __size = 0;
+ std::vector<std::string> fields;
+ std::vector<std::string> bindings;
+private:
};
enum class Operator
{
-ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, CALL, NONE, IMPL/* implication */, MAP, FOLD, INDEX, IF
+ADD, SUB, MUL, DIV, EQU, LSS, GTR, NEG, LIST, LIST_RANGE, LIST_NAMED, CALL, NONE, IMPL/* implication */, MAP, FOLD, INDEX, IF
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
template<class Target>
struct ManagedPtr
{
- 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
{
- return *(*__storage).at(__id);
+ 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());
+ assert(isValid() && "Invalid Ptr");
return __storage->at(__id);
}
inline bool isValid() const
{
return (__storage) && (0 <= __id) && (__id < __storage->size());
}
+ inline operator bool() const {
+ return isValid();
+ }
+
ManagedPtr<Target>& operator++()
{
++__id;
return *this;
}
inline unsigned int id()
{
return __id;
}
private:
unsigned int __id =0;
const std::vector<Target*> * __storage=0;
};
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
struct Expression
{
friend class CodeScope;
friend class ClaspLayer;
friend class CFGPass;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
+ Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
+ void bindType(TypeAnnotation&& t);
+
+ template<class InputIt>
+ void addBindings(InputIt paramsBegin, InputIt paramsEnd);
+
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
const std::string& getValueString() const;
+ void setValue(const Atom<Identifier_t>&& v);
+ bool isNone() const;
+ bool isValid() const;
Operator op;
- enum {INVALID, COMPOUND, IDENT, NUMBER, STRING} __state;
+ enum {INVALID, COMPOUND, IDENT, NUMBER, STRING, NONE} __state = INVALID;
std::vector<std::string> bindings;
- std::list<ManagedScpPtr> blocks;
+ std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
+ TypeAnnotation type;
+
+ std::map<std::string, Expression> tags;
+ std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
+
+
};
+template<class InputIt>
+void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
+ size_t index = bindings.size();
+
+ std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
+ [&index, this] (const Atom<Identifier_t> atom){
+ std::string key = atom.get();
+ this->__indexBindings[key] = index++;
+ return key;
+ });
+}
+
typedef std::list<Expression> ExpressionList;
enum class TagModifier
{NONE, ASSERT, REQUIRE};
enum class DomainAnnotation
{FUNCTION, VARIABLE};
class RuleArguments: public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards: public std::vector<Expression>
{
public:
void add(Expression&& e);
};
class ClaspLayer;
class LLVMLayer;
class MetaRuleAbstract
{
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(ClaspLayer& layer) =0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning: public MetaRuleAbstract
{
friend class ClaspLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(ClaspLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VID;
/*
class Expression: ExpressionAbstract
{
friend class CFGPass;
public:
llvm::Value* compile(LLVMLayer& l, Function* f, std::string* hintRetVar=0) const;
};
*/
typedef std::pair<VID, TypeAnnotation> VariableDefinition;
typedef std::pair<VID, Expression> VariableDeclaration;
typedef std::pair<Expression, TagModifier> Tag;
struct Symbol
{
VID identifier;
CodeScope * scope;
};
+struct SymbolTags_t{};
+
+template<>
+struct AttachmentsDict<SymbolTags_t> {
+ typedef std::map<std::string, Expression> Data;
+ static const unsigned int key = 2;
+};
+
bool operator< (const Symbol& s1, const Symbol& s2);
bool operator== (const Symbol& s1, const Symbol& s2);
class CodeScope
{
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent=0);
void setBody(const Expression& body);
void addDeclaration(const Atom <Identifier_t> &&name, TypeAnnotation &&typ, Expression&& body);
void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
- void bindArg(llvm::Value* var, std::string&& name);
+
//TODO exclude forceCompile partz
- Symbol findSymbol(const std::string &name, LLVMLayer &l, bool forceCompile=false);
+ Symbol findSymbol(const std::string &name);
static const Expression& findDeclaration(const Symbol& symbol);
static TypeAnnotation& findDefinition(const Symbol& symbol);
static bool hasDeclaration(const Symbol& symbol);
- static llvm::Value* compileExpression(const Symbol& s, LLVMLayer& l, std::string hintRetVar="");
- llvm::Value* compile(LLVMLayer &l, const std::string & hintBlockName="");
-
~CodeScope();
std::vector<std::string> __args;
Expression __body; //TODO move __body to __declarations[0]
- std::map<VID,llvm::Value*> __rawVars;
- virtual llvm::Value* compileExpression(const Expression& expr, LLVMLayer& l, std::string hintRetVar="");
+
SymbolAttachments attachments;
-protected:
+ std::map<std::string, VID> __vartable;
/**
- * definition of return type have variable index Zero(0)
+ * definition of return type has variable index Zero(0)
*/
//TODO move __definitions to SymbolsAttachments data
std::unordered_map<VariableDefinition::first_type, VariableDefinition::second_type> __definitions;
std::unordered_map<VariableDeclaration::first_type, VariableDeclaration::second_type> __declarations;
- std::map<std::string, VID> __vartable;
+protected:
+
+
VID __vCounter=1;
CodeScope* __parent;
std::list<CodeScope*> __storage;
VID registerVar(std::string&& name, TypeAnnotation &&typ);
-
};
class Function
{
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
void addArg(Atom <Identifier_t>&& name, TypeAnnotation&& typ);
void addTag(Expression&& tag, const TagModifier mod);
void setReturnType(const TypeAnnotation& rtyp);
const std::string& getName() const;
-
- llvm::Function* compile(LLVMLayer& l);
const std::vector<Tag>& getAnnotations() const;
CodeScope* getEntryScope() const;
-private:
-
CodeScope* __entry;
std::string __name;
+private:
+
std::vector<Tag> __tags;
+};
- llvm::Function* __raw;
-};
+class ExternData;
+struct ExternEntry {
+ std::string package;
+ std::vector<std::string> headers;
+};
+typedef Expanded<TypeAnnotation> ExpandedType;
class AST
{
public:
AST();
+
+ /**
+ * DFA Interface
+ */
+ void addDFAData(Expression&& data);
+
+ /**
+ * Extern Interface
+ */
+ void addExternData(ExternData&& data);
+
void add(Function* f);
void add(MetaRuleAbstract* r);
- void addDFAData(Expression&& data);
ManagedScpPtr add(CodeScope* scope);
- void compile(LLVMLayer& l);
- void run(LLVMLayer& l);
-
std::string getModuleName();
-
ManagedPtr<Function> findFunction(const std::string& name);
+
template<class Target>
ManagedPtr<Target> begin();
+ std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
+
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
-
std::map<std::string, unsigned int> __indexFunctions;
+
+
+ // ***** TYPES SECTION *****
+ public:
+std::map<std::string, TypeAnnotation> __indexTypeAliases;
+ExpandedType expandType(const TypeAnnotation &t) const;
+ExpandedType findType(const std::string& name);
+void add(TypeAnnotation&& t, Atom<Identifier_t>&& alias);
+
+ private:
+ExpandedType expandType(const TypeAnnotation &t, std::map<std::string, TypeAnnotation> scope,
+ const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) const;
+
+ // ***** TYPES SECTION END *****
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
+
}
#endif // AST_H
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index 1b79036..08b8579 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,109 +1,143 @@
//
// Created by pgess on 3/15/15.
//
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <map>
+#include <assert.h>
+#include <type_traits>
namespace xreate
{
//Attachemnt Tags:
struct IsDeclVisited{};
+ struct IsImplementationOnTheFly{};
//Atachments dictionary
template<class Tag>
- struct AttachmentsDictionary
+ struct AttachmentsDict
{
// typedef void Data;
};
template<>
- struct AttachmentsDictionary<IsDeclVisited>
+ struct AttachmentsDict<IsDeclVisited>
{
typedef bool Data;
static const unsigned int key = 0;
};
+ template<>
+ struct AttachmentsDict<IsImplementationOnTheFly>
+ {
+ typedef bool Data;
+ static const unsigned int key = 3;
+ };
+
class Symbol;
typedef unsigned int VID;
class AttachmentsImpl
{
friend class SymbolAttachments;
};
//TODO copy function to copy whole data from symbol to symbol: copy(sTo, sFrom);
class SymbolAttachments
{
public:
//TODO add specialization for pointers
template<class Tag>
- static void put(const Symbol& symbol, typename AttachmentsDictionary<Tag>::Data && data)
+ using Data = typename AttachmentsDict<Tag>::Data;
+
+ template<class Tag>
+ using Input = typename std::conditional<std::is_pointer<Data<Tag>>::value, Data<Tag>, Data<Tag>&&>::type;
+
+ template<class Tag>
+ static typename std::enable_if<std::is_pointer<Data<Tag>>::value>::type
+ put(const Symbol& symbol, Input<Tag> data)
{
- typedef typename AttachmentsDictionary<Tag>::Data Typ;
- const unsigned int key = AttachmentsDictionary<Tag>::key;
- Typ* ptr = new Typ(data);
+ const unsigned int key = AttachmentsDict<Tag>::key;
+ put(symbol, key, (void*) data);
+ }
- put(symbol, key, ptr);
+ template<class Tag>
+ static typename std::enable_if<! std::is_pointer<Data<Tag>>::value>::type
+ put(const Symbol& symbol, Input<Tag> data)
+ {
+ const unsigned int key = AttachmentsDict<Tag>::key;
+ Data<Tag>* holder = new Data<Tag>(data);
+ put(symbol, key, (void*) holder);
}
/*
template<class Tag>
using Tag2 = std::enable_if<std::is_pointer<Tag>, Tag>::
- static void put(const Symbol& symbol, typename AttachmentsDictionary<Tag>::Data && data)
+ static void put(const Symbol& symbol, typename AttachmentsDict<Tag>::Data && data)
{
- typedef typename AttachmentsDictionary<Tag>::Data Typ;
+ typedef typename AttachmentsDict<Tag>::Data Typ;
Typ* ptr = new Typ(data);
AttachmentsImpl::put(symbol, ptr);
}
*/
template<class Tag>
- static typename AttachmentsDictionary<Tag>::Data& get(const Symbol& symbol, typename AttachmentsDictionary<Tag>::Data&& valueDefault)
+ static typename AttachmentsDict<Tag>::Data& get(const Symbol& symbol, typename AttachmentsDict<Tag>::Data&& valueDefault)
{
- typedef typename AttachmentsDictionary<Tag>::Data Typ;
- const unsigned int key = AttachmentsDictionary<Tag>::key;
+ typedef typename AttachmentsDict<Tag>::Data Typ;
+ const unsigned int key = AttachmentsDict<Tag>::key;
Typ* def = new Typ(valueDefault);
Typ* result = static_cast<Typ*> (get(symbol, key, def));
- if (result != def) delete def;
+ if (result != def) delete def; //TODO check is there some mem leaks?
return *result;
}
template<class Tag>
- static typename AttachmentsDictionary<Tag>::Data& get(const Symbol& symbol)
+ static typename std::enable_if<std::is_pointer<Data<Tag>>::value, Data<Tag>>::type
+ get(const Symbol& symbol)
+ {
+ const unsigned int key = AttachmentsDict<Tag>::key;
+ Data<Tag> result = reinterpret_cast<Data<Tag>> (get(symbol, key, nullptr));
+
+ assert(result != nullptr); // data not found for the symbol
+ return result;
+ }
+
+ template<class Tag>
+ static typename std::enable_if<! std::is_pointer<Data<Tag>>::value, Data<Tag>&>::type
+ get(const Symbol& symbol)
{
- typedef typename AttachmentsDictionary<Tag>::Data Typ;
- const unsigned int key = AttachmentsDictionary<Tag>::key;
+ const unsigned int key = AttachmentsDict<Tag>::key;
- Typ* result = static_cast<Typ*> (get(symbol, key, nullptr));
+ Data<Tag>* result = reinterpret_cast<Data<Tag>*> (get(symbol, key, nullptr));
assert(result != nullptr); // data not found for the symbol
return *result;
}
template<class Tag>
static bool exists(const Symbol& symbol)
{
- const unsigned int key = AttachmentsDictionary<Tag>::key;
+ const unsigned int key = AttachmentsDict<Tag>::key;
return exists(symbol, key);
}
private:
typedef std::map<VID, void*> Attachment;
std::map<unsigned int, Attachment> __data;
static void put(const Symbol& symbol, unsigned int key, void* data);
static void* get(const Symbol& symbol, unsigned int key, void *def);
static bool exists(const Symbol& symbol, unsigned int key);
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp
index b9707e8..34a7708 100644
--- a/cpp/src/clasplayer.cpp
+++ b/cpp/src/clasplayer.cpp
@@ -1,466 +1,482 @@
#include "clasplayer.h"
#include <clasp/program_builder.h> // for defining logic programs
#include <clasp/unfounded_check.h> // unfounded set checkers
#include <clasp/model_enumerators.h> // for enumerating answer sets
#include <clasp/clasp_facade.h>
#include <clingocontrol.hh>
#include <iostream>
#include <clingo_lib.hh>
+#include "utils.h"
using namespace std;
namespace xreate {
void
ClaspLayer::printWarnings(std::ostream& out)
{
const std::string warningTag = "warning";
auto warningsRange = __model.equal_range(warningTag);
for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) {
unsigned int warningId;
Gringo::Value params;
std::tie(warningId, params) = parse<unsigned int, Gringo::Value>(warning->second);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out<<params;
}
}
bool
ClaspLayer::onModel(Gringo::Model const &model) {
std::list<std::string> warnings;
cout << "Model: " << endl;
+
+ const string& atomBindVar = Config::get("clasp.bindings.variable");
+ const string& atomBindFunc = Config::get("clasp.bindings.function");
+
for (Gringo::Value atom : model.atoms(Gringo::Model::ATOMS)) {
atom.print(cout);
- cout << endl;
+ cout <<" | "<< endl;
+
+ if (*atom.name() == atomBindVar || *atom.name() == atomBindFunc){
+ string name = *std::get<1>(parse<Gringo::Value, Gringo::Value>(atom)).name();
+ __model.emplace(move(name), move(atom));
+ continue;
+ }
__model.emplace(*atom.name(), move(atom));
}
+
+ return true;
}
QStringList multiplyLists(std::list<QStringList> &&lists) {
QStringList result = lists.front();
lists.pop_front();
for (QStringList &list: lists) {
QStringList::const_iterator end = result.end();
for (QStringList::iterator expr1I = result.begin(); expr1I < end; ++expr1I) {
if (list.size() == 0) continue;
QStringList::const_iterator expr2I = list.begin();
for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
result.append(QString("%1, %2").arg(*expr1I).arg(*expr2I));
*expr1I = QString("%1, %2").arg(*expr1I).arg(*expr2I);
}
}
return result;
}
void
ClaspLayer::addCFAData(CFGraph &&graph) {
ostream &cout = __partGeneral;
cout << endl << "%\t\tStatic analysis: CFA" << endl;
for (const std::pair<unsigned int, unsigned int> &relation: graph.__relations) {
const string &tagFrom = graph.__nodes.at(relation.first);
const string &tagTo = graph.__nodes.at(relation.second);
cout << (QString("call(%1, %2) .").arg(tagFrom.c_str()).arg(tagTo.c_str())).toStdString() << endl;
}
}
void
- ClaspLayer::addDFAData(DFGraph &&graph)
+ ClaspLayer::addDFAData(DFAGraph &&graph)
{
- dfgData = graph;
+ dfaData = graph;
std::set<SymbolPacked> symbols;
ostream &cout = __partGeneral;
cout << endl << "%\t\tStatic analysis: DFA" << endl;
std::vector<std::pair<SymbolPacked, SymbolPacked>>::iterator i1;
std::vector<DFGConnection>::iterator i2;
- for (i1=dfgData.__edges.begin(), i2 = dfgData.__data.begin(); i1!= dfgData.__edges.end(); ++i1, ++i2 )
+ for (i1= dfaData.__edges.begin(), i2 = dfaData.__data.begin(); i1!= dfaData.__edges.end(); ++i1, ++i2 )
{
QString edgeData;
switch (*i2)
{
case DFGConnection::OPT: edgeData = "opt"; break;
- case DFGConnection::STRONG: edgeData = "strong"; break;
+ case DFGConnection::ALIAS: edgeData = "alias"; break;
case DFGConnection::PROTO: edgeData = "proto"; break;
}
cout << QString("dfa_connection(%1, %2, %3).")
.arg(QString("(%1, %2)").arg(i1->first.identifier).arg(i1->first.scope))
.arg(QString("(%1, %2)").arg(i1->second.identifier).arg(i1->second.scope))
.arg(edgeData).toStdString() << endl;
symbols.insert(i1->first);
symbols.insert(i1->second);
}
- for (const pair<SymbolPacked, Expression>& tag: dfgData.__tags)
+ for (const pair<SymbolPacked, Expression>& tag: dfaData.__tags)
{
for (QString variant: compile(tag.second)) {
cout << QString("bind(%1, %2).")
.arg(QString("(%1, %2)").arg(tag.first.identifier).arg(tag.first.scope))
.arg(variant).toStdString()<<endl;
}
symbols.insert(tag.first);
}
for (const SymbolPacked& s: symbols)
{
cout << QString("v((%1, %2)).").arg(s.identifier). arg(s.scope).toStdString()<<endl;
}
}
void
ClaspLayer::addFunctionTags(const std::string &function, const std::vector<Tag> &tags) {
ostream &cout = __partTags;
cout << (QString("function(%1) .").arg(function.c_str())).toStdString() << std::endl;
int tagsCount = 0;
for (const Tag &tag: tags) {
QStringList tagRaw = compile(tag.first);
assert(tagRaw.size() == 1);
- cout << QString("tag(%1, %2).").arg(function.c_str()).arg(tagRaw.at(0)).toStdString() << endl;
+ std::string atom_binding = Config::get("clasp.bindings.function");
+ cout << QString("%1(%2, %3).").arg(atom_binding.c_str()).arg(function.c_str()).arg(tagRaw.at(0)).toStdString() << endl;
++tagsCount;
}
+
if (tagsCount == 0) {
cout << "%no tags at all" << endl;
}
}
void
ClaspLayer::addRuleWarning(const RuleWarning &rule) {
//__partGeneral << rule << endl;
QStringList domains;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch (argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return QString("%1(%2)").arg(domain.c_str()).arg(argument.first.c_str());
});
QStringList vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
std::list<QStringList> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression &guard) {
return compile(guard);
});
QStringList guards = multiplyLists(std::move(guardsRaw));
QStringList &&branches = compileNeg(rule.__condition);
for (const QString &guardsJoined: guards)
for (const QString &branch: branches) {
unsigned int hook = registerWarning(string(rule.__message));
QString result = QString("warning(%1, (%2)):- %3, %4, %5.")
.arg(hook)
.arg(vars.join(", "))
.arg(branch)
.arg(guardsJoined)
.arg(domains.join(", "));
__partGeneral << result.toStdString() << endl;
}
}
QStringList
ClaspLayer::compile(const Expression &e) const {
QStringList result;
switch (e.op) {
case Operator::CALL: {
assert(e.__state == Expression::COMPOUND);
std::list<QStringList> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[this](const Expression &e) {
return compile(e);
});
QStringList &&operands_ = multiplyLists(std::move(operands));
result.append(QString("%1(%2)").arg(e.__valueS.c_str()).arg(operands_.join(", ")));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
QStringList &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.append(QString("not %1").arg(rawOp.at(0)));
break;
};
case Operator::NONE: {
switch (e.__state) {
case Expression::IDENT:
result.append(QString(e.__valueS.c_str()));
break;
case Expression::NUMBER:
result.append(QString::number(e.__valueD));
break;
default:
assert(true);
}
break;
}
}
return result;
}
QStringList
ClaspLayer::compileNeg(const Expression &e) const {
QStringList result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
QStringList operands1 = compile(e.operands.at(0));
QStringList operands2 = compile(e.operands.at(1));
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.append(QString("%1, not %2").arg(op1).arg(op2));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
QStringList &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.append(rawOp.at(0));
break;
};
default:
assert(true);
}
return result;
}
unsigned int
ClaspLayer::registerWarning(std::string &&message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;;
}
void
ClaspLayer::addImports() {
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::run() {
addImports();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
- cout << program.str() << endl;
+ cout << FYEL(program.str()) << endl;
const char *argv[] = {nullptr, nullptr};
ClingoLib ctl(2, argv);
//prg.add("p", ["t"], "q(t).")
Gringo::FWStringVec vars{};
ctl.add("base", vars, program.str());
//prg.ground([("p", [2])])
Gringo::Control::GroundVec vals{std::make_pair("base", Gringo::FWValVec {})};
ctl.ground(vals, Gringo::Any());
//solve
Gringo::Control::Assumptions as;
Gringo::SolveResult result = ctl.solve(Gringo::Control::ModelHandler([&](Gringo::Model const &model) {
return this->onModel(model);
}), std::move(as));
if (result == Gringo::SolveResult::SAT) {
- cout << "SUCCESSFULLY" << endl;
+ cout << FGRN("SUCCESSFULLY") << endl;
} else {
- cout << "UNSUCCESSFULLY" << endl;
+ cout << FRED("UNSUCCESSFULLY") << endl;
}
// invoke all query plugins to process clasp data
for (IQuery* q: __queries)
{
q->init(this);
}
}
ClaspLayer::ClaspLayer() {
}
- std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>
+ ClaspLayer::ModelRange
ClaspLayer::query(const std::string& atom)
{
- return __model.equal_range(atom);
+ if (! __model.count(atom)){
+ return boost::none;
+ }
+
+ return ModelRange(__model.equal_range(atom));
+ }
+
+ SymbolPacked
+ ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName)
+ {
+ auto pos = __indexScopes.emplace(symbol.scope, __indexScopes.size());
+ if (pos.second)
+ __registryScopes.push_back(symbol.scope);
+
+ SymbolPacked result;
+ result.scope = pos.first->second;
+ result.identifier = symbol.identifier;
+
+ return result;
}
+ Symbol
+ ClaspLayer::unpack(const SymbolPacked& symbol)
+ {
+ return Symbol{symbol.identifier, __registryScopes[symbol.scope]};
+ };
+
/*
void AspOutPrinter::reportSolution(const Clasp::Solver&, const Clasp::Enumerator&, bool complete) {
if (complete) std::cout << "No more models!" << std::endl;
else std::cout << "More models possible!" << std::endl;
}
void AspOutPrinter::reportModel(const Clasp::Solver& s, const Clasp::Enumerator&) {
std::cout << "Model " << s.stats.solve.models << ": \n";
// get the symbol table from the solver
const Clasp::AtomIndex& symTab = *s.strategies().symTab;
for (Clasp::AtomIndex::const_iterator it = symTab.begin(); it != symTab.end(); ++it)
{
// print each named atom that is true w.r.t the current assignment
}
std::cout << std::endl;
}
*/
/*****************************************
* CFGraph
*****************************************
*/
void
CFGraph::addNode(unsigned int function, std::string &&tag) {
__nodes.emplace(function, tag);
}
bool
CFGraph::existsNode(unsigned int function) const {
return __nodes.count(function);
}
void
CFGraph::addLink(unsigned int nodeFrom, unsigned int nodeTo) {
__relations.insert(std::make_pair(nodeFrom, nodeTo));
}
/*****************************************
- * DFGraph
+ * DFAGraph
*****************************************
*/
bool
- DFGraph::linkExists(const SymbolPacked& node1, const SymbolPacked& node2)
+ DFAGraph::linkExists(const SymbolPacked& node1, const SymbolPacked& node2)
{
auto range = __outEdges.equal_range(node2);
for(std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge)
{
if (__edges[edge->second].second == node1)
return true;
}
return false;
}
void
- DFGraph::addLink(const SymbolPacked& nodeTo, const SymbolPacked& nodeFrom, DFGConnection link) {
+ DFAGraph::addLink(const SymbolPacked& nodeTo, const SymbolPacked& nodeFrom, DFGConnection link) {
if (!linkExists(nodeTo, nodeFrom))
{
__edges.emplace_back(nodeTo, nodeFrom);
__data.push_back(link);
EdgeId eid = __edges.size()-1;
__outEdges.emplace(nodeFrom, eid);
}
}
void
- DFGraph::addTag(const SymbolPacked &node, Expression &&tag) {
+ DFAGraph::addTag(const SymbolPacked &node, Expression &&tag) {
__tags.emplace(node, tag);
}
- SymbolPacked
- DFGraph::pack(const Symbol& symbol, std::string hintSymbolName)
- {
- std::unordered_map<const CodeScope*, unsigned int>::iterator pos
- = __hash.emplace(symbol.scope, __hash.size()).first;
- __hashedScopes.push_back(symbol.scope);
-
- SymbolPacked result;
- result.scope = pos->second;
- result.identifier = symbol.identifier;
- }
-
- Symbol
- DFGraph::unpack(const SymbolPacked& symbol)
- {
- return Symbol{symbol.identifier, __hashedScopes[symbol.scope]};
- };
-
- bool SymbolPacked::isValid() const
- {
- return this->scope != SYMBOL_INVALID.scope && identifier != SYMBOL_INVALID.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);
}
void ClaspLayer::registerdQuery(IQuery *query) {
__queries.push_back(query);
}
-}
\ No newline at end of file
+}
diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h
index 3e883aa..9fb1f8f 100644
--- a/cpp/src/clasplayer.h
+++ b/cpp/src/clasplayer.h
@@ -1,173 +1,172 @@
#ifndef CLASPLAYER_H
#define CLASPLAYER_H
#include <string>
#include <gringo/control.hh>
#include <ast.h>
#include <QStringList>
#include <climits>
+#include <boost/optional.hpp>
namespace xreate {
class CFGraph {
friend class ClaspLayer;
public:
void addNode(unsigned int function, std::string &&tag);
void addLink(unsigned int nodeFrom, unsigned int nodeTo);
bool existsNode(unsigned int function) const;
void print(std::ostream &cout) const;
private:
std::map<unsigned int, unsigned int> __relations;
std::map<unsigned int, std::string> __nodes;
};
- enum class DFGConnection{
- STRONG, OPT, PROTO};
-
-
struct SymbolPacked
{
VID identifier;
unsigned int scope;
-
- bool isValid() const;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
- const SymbolPacked SYMBOL_INVALID{UINT_MAX, UINT_MAX};
+ enum class DFGConnection{
+ ALIAS, OPT, PROTO};
- class DFGraph
+ class DFAGraph
{
friend class ClaspLayer;
public:
void addTag(const SymbolPacked& node, Expression&& tag);
void addLink(const SymbolPacked& nodeTo, const SymbolPacked& nodeFrom, DFGConnection link);
bool linkExists(const SymbolPacked& node1, const SymbolPacked& node2);
- SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
- Symbol unpack(const SymbolPacked& symbol);
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::unordered_map<const CodeScope*, unsigned int> __hash;
- std::vector<CodeScope*> __hashedScopes;
};
- class IQuery
- {
+ class IQuery {
public:
virtual void init(ClaspLayer* clasp)=0;
virtual ~IQuery() {}
};
class ClaspLayer {
public:
AST *ast;
- DFGraph dfgData;
+ DFAGraph dfaData;
ClaspLayer();
void registerdQuery(IQuery* query);
void addFunctionTags(const std::string &function, const std::vector<Tag> &tags);
void addCFAData(CFGraph &&graph);
- void addDFAData(DFGraph &&graph);
+ void addDFAData(DFAGraph &&graph);
void addRuleWarning(const RuleWarning &rule);
void run();
template<class ...Types>
static std::tuple<Types...> parse(const Gringo::Value& atom);
typedef std::multimap<std::string, Gringo::Value>::const_iterator ModelIterator;
- std::pair<ModelIterator, ModelIterator> query(const std::string& atom);
+ typedef boost::optional<std::pair<ClaspLayer::ModelIterator, ClaspLayer::ModelIterator>> ModelRange;
+ ModelRange query(const std::string& atom);
+
+ SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName="");
+ Symbol unpack(const SymbolPacked& symbol);
private:
// all query plugins to process clasp data
std::list<IQuery*> __queries;
std::multimap<std::string, Gringo::Value> __model;
std::map<unsigned int, std::string> __warnings;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
+ std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
+ std::vector<CodeScope*> __registryScopes;
+
void printWarnings(std::ostream& out);
bool onModel(Gringo::Model const &model);
QStringList compile(const Expression &e) const;
QStringList compileNeg(const Expression &e) const;
unsigned int registerWarning(std::string &&message);
void addImports();
+
+
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Value& atom)
{
return atom.num();
}
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Value& atom)
{
return *atom.string();
}};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Value& atom)
{
auto result = ClaspLayer::parse<unsigned int, unsigned int>(atom);
return SymbolPacked{std::get<0>(result), std::get<1>(result)};
}};
template<>
struct ParseImplAtom<Gringo::Value> {
static Gringo::Value get(const Gringo::Value& atom)
{
return atom;
}};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
{
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element<tupleSize - index, Tuple>::type ElType;
ElType& el = std::get<tupleSize - index>(tup);
Gringo::Value atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index-1>::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0>
{
static void parse(Tuple& tup, Gringo::FWValVec::const_iterator arg)
{}
};
template<class ...Types>
std::tuple<Types...>
ClaspLayer::parse(const Gringo::Value& atom)
{
typedef std::tuple<Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().begin());
return tup;
}
}
#endif
diff --git a/cpp/src/instructions/instr-containers.cpp b/cpp/src/instructions/instr-containers.cpp
index bbfb330..1cc1e05 100644
--- a/cpp/src/instructions/instr-containers.cpp
+++ b/cpp/src/instructions/instr-containers.cpp
@@ -1,276 +1,469 @@
#include "instr-containers.h"
#include "llvmlayer.h"
#include "ast.h"
#include "query/containers.h"
+#include "query/ptrvalid.h"
using namespace std;
using namespace llvm;
+using namespace xreate;
using namespace xreate::containers;
-xreate::containers::Instructions::Instructions(CodeScope *current, LLVMLayer* layer)
- : scope(current), llvm(layer),
- tyNum (static_cast<llvm::IntegerType*> (TypeAnnotation(TypePrimitive::Num).toLLVMType()))
-{}
-
-Value*
-Instructions::compileIndex(const Symbol& dataSymbol, std::vector<llvm::Value*> indexes, std::string ident)
-{
- #define NAME(x) (ident.empty()? x : ident)
-
- const ImplementationData& info = containers::Query::queryImplementation(dataSymbol);
- llvm::Value* data = dataSymbol.scope->__rawVars.at(dataSymbol.identifier);
-
- switch (info.impl)
- {
- case containers::LLVM_CONST_ARRAY: {
- assert(indexes.size() == 1);
- return llvm->builder.CreateExtractElement(data, indexes[0], NAME("el"));
- }
-
- case containers::LLVM_ARRAY: {
- indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
- Value *pEl = llvm->builder.CreateGEP(data, llvm::ArrayRef<llvm::Value *>(indexes));
- return llvm->builder.CreateLoad(pEl, NAME("el"));
- }
-
- default:
- // non supported container implementation
- assert(false);
- }
-}
-
-Value*
-Instructions::compileGetElement(std::string varIn, Value* stateLoop, std::string ident)
-{
- #define NAME(x) (ident.empty()? x : ident)
- llvm::IRBuilder<> &builder = llvm->builder;
-
- const Symbol& symbolIn = scope->findSymbol(varIn, *llvm);
- const Expression& exprIn = CodeScope::findDeclaration(symbolIn);
-
- if (exprIn.op == Operator::LIST_RANGE)
- {return stateLoop; }
-
- if (exprIn.op == Operator::LIST)
- {
- llvm::Value* dataIn = CodeScope::compileExpression(symbolIn, *llvm);
- return compileIndex(symbolIn, vector<Value*>{stateLoop}, NAME(string("el_") + varIn));
- }
-
- if(exprIn.op == Operator::MAP)
- {
- assert(exprIn.getOperands().size()==1);
- assert(exprIn.bindings.size());
- assert(exprIn.blocks.size());
-
- const ManagedScpPtr& scopeLoop = exprIn.blocks.front();
- const std::string& varIn2 = exprIn.getOperands()[0].getValueString();
- std::string varEl = exprIn.bindings[0];
-
- Value* elIn = compileGetElement(varIn2, stateLoop, varEl);
- scopeLoop->bindArg(elIn, move(varEl));
- return scopeLoop->compileExpression(scopeLoop->__body, *llvm, NAME(string("el_") + varIn));
- }
-
- assert(false);
-
-
+#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
- /*
- switch(implIn.impl)
- {
- case containers::LLVM_ARRAY:
- case containers::LLVM_CONST_ARRAY:
- stateLoopNext = builder.CreateAdd(stateLoop, ConstantInt::get(tyNum, 1));
-
-
- case containers::ON_THE_FLY:
- stateLoopNext = compileIndexLoad(stateLoad);
- }
- */
+#define EXPAND_CONTEXT \
+ LLVMLayer* llvm = context.pass->man->llvm; \
+ CompilePass::CodeScopeUnit* scope = context.scope; \
+ CompilePass::FunctionUnit* function = context.function; \
-}
+Instructions::Instructions(CompilePass::Context ctx)
+ : context(ctx), tyNum (static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num)))))
+{}
llvm::Value*
-Instructions::compileMapArray(const Expression &expr, const std::string ident) {
- #define NAME(x) (ident.empty()? x : ident)
+Instructions::compileMapSolid(const Expression &expr, const std::string hintRetVar) {
+ EXPAND_CONTEXT
//initialization
std::string varIn = expr.getOperands()[0].getValueString();
- Symbol symbolIn = scope->findSymbol(varIn, *llvm);
+ Symbol symbolIn = scope->scope->findSymbol(varIn);
- containers::ImplementationData implIn = containers::Query::queryImplementation(symbolIn); // impl of input list
- unsigned int size = implIn.size;
- ManagedScpPtr scopeLoop = expr.blocks.front();
+ ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
+ size_t size = implIn.size;
+ CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__args[0];
- llvm::Value *rangeFrom = ConstantInt::get((tyNum), 0);
- llvm::Value *rangeTo = ConstantInt::get((tyNum), size-1);
+ Iterator* it = Iterator::create(context, symbolIn);
+ llvm::Value *rangeFrom = it->begin();
+ llvm::Value *rangeTo = it->end();
//definitions
- ArrayType* tyNumArray = (ArrayType*) (TypeAnnotation(tag_array, TypePrimitive::Num, size).toLLVMType());
+ 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", llvm->context.function);
+ 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", llvm->context.function);
+ 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 = compileGetElement(varIn, stateLoop, varEl);
- scopeLoop->bindArg(elIn, move(varEl));
- Value* elOut = scopeLoop->compileExpression(scopeLoop->__body, *llvm);
+ Value* elIn = it->get(stateLoop, varEl);
+ CompilePass::CodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
+ scopeLoopUnit->bindArg(elIn, move(varEl));
+ Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop,llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, blockLoop);
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
+Value*
+Instructions::compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string hintRetVar)
+{
+ EXPAND_CONTEXT
+
+ //TODO find out symbol identifier in order to name it in raw llvm;
+ llvm::Value* data = scope->compileSymbol(dataSymbol);
+ const Expression& decl = CodeScope::findDeclaration(dataSymbol);
+
+ if (decl.op == Operator::LIST) {
+ assert(indexes.size() == 1);
+ return llvm->builder.CreateExtractElement(data, indexes[0], NAME("el"));
+ }
+
+
+ indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
+ Value *pEl = llvm->builder.CreateGEP(data, llvm::ArrayRef<llvm::Value *>(indexes));
+ return llvm->builder.CreateLoad(pEl, NAME("el"));
+}
+
+Value*
+Instructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx){
+ EXPAND_CONTEXT
+
+ PointerType* tyInt8P = PointerType::getInt8PtrTy(llvm::getGlobalContext());
+ Value* nullInt8P = llvm::ConstantPointerNull::get(tyInt8P);
+
+ TypeUtils types(llvm);
+
+ std::vector<std::string>&& fields = types.getStructFields(t);
+ for (unsigned i=0, size = fields.size(); i<size; ++i){
+ if (fields.at(i) == idx){
+
+ std::vector<llvm::Value*> refs;
+
+ llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm::getGlobalContext());
+ llvm::ConstantInt* zero = llvm::ConstantInt::get(tyInt, 0, false);
+
+ llvm::BasicBlock *blockSafe = llvm::BasicBlock::Create(llvm::getGlobalContext(), "safe", function->raw);
+ llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
+
+ // safety check: not null ptr
+ Symbol s;
+ if (! QueryPtrValid::assertValidPtr(s)){
+ PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
+ llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
+ Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
+ llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
+ }
+
+ llvm->builder.SetInsertPoint(blockException);
+
+ llvm->initExceptionsSupport();
+ llvm::Function* fAllocate = llvm->module->getFunction("__cxa_allocate_exception");
+ llvm::Function* fThrow = llvm->module->getFunction("__cxa_throw");
+ auto exception = llvm->builder.CreateCall(fAllocate, ConstantInt::get(IntegerType::getInt64Ty(getGlobalContext()), 4));
+ vector<Value*> throwParams{exception, nullInt8P, nullInt8P};
+ llvm->builder.CreateCall(fThrow, ArrayRef<Value*>(throwParams));
+ llvm->builder.CreateUnreachable();
+
+
+ llvm->builder.SetInsertPoint(blockSafe);
+ std::vector<Value*> indexes;
+
+ //dereference pointer
+ if (types.isPointer(t)){
+ indexes.push_back(zero);
+ }
+ indexes.push_back(ConstantInt::get(tyInt, i));
+
+ Value* addr = llvm->builder.CreateGEP(aggregate, indexes);
+ return llvm->builder.CreateLoad(addr);
+
+
+ }
+ }
+
+ assert(false && "not found required struct field");
+}
+
llvm::Value*
-Instructions::compileFold(const Expression& fold, const std::string& ident)
+Instructions::compileFold(const Expression& fold, const std::string& hintRetVar)
{
- #define NAME(x) (ident.empty()? x : ident)
+ EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
- Symbol varInSymbol = scope->findSymbol(fold.getOperands()[0].getValueString(), *llvm);
- ImplementationData info = Query::queryImplementation(varInSymbol);
- const pair<Expression, Expression>& range = info.getRange();
- llvm::Value* rangeFrom = scope->compileExpression(range.first, *llvm);
- llvm::Value* rangeTo = scope->compileExpression(range.second, *llvm);
- llvm::Value* accumInit = scope->compileExpression(fold.getOperands()[1], *llvm);
+ Symbol varInSymbol = scope->scope->findSymbol(fold.getOperands()[0].getValueString());
+ Implementation info = Query::queryImplementation(varInSymbol);
+
+ Iterator* it = Iterator::create(context, varInSymbol);
+ llvm::Value* rangeFrom = it->begin();
+ llvm::Value* rangeTo = it->end();
+ llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
llvm::Value* valSat;
bool flagHasSaturation = false; //false; // TODO add `saturation` ann.
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
- llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", llvm->context.function);
- llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", llvm->context.function);
+ llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
+ llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postfold", function->raw);
+ llvm::BasicBlock *blockEarly = llvm::BasicBlock::Create(llvm::getGlobalContext(), "earlyret", function->raw);
+
+
// * initial check
- Value* condBefore = llvm->builder.CreateICmpSLE(rangeFrom, rangeTo);
- llvm->builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
+ Value* condBefore = llvm->builder.CreateICmpNE(rangeFrom, rangeTo);
+ llvm->builder.CreateCondBr(condBefore, blockLoop, blockEarly);
+ llvm->builder.SetInsertPoint(blockEarly);
+ llvm->builder.CreateRet(accumInit);
+ // Saturation check
if (flagHasSaturation)
{
Value* condSat = llvm->builder.CreateICmpNE(accumInit, valSat);
llvm->builder.CreateCondBr(condSat, blockLoop, blockAfterLoop);
}
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(tyNum, 2, NAME("accum"));
accum->addIncoming(accumInit, blockBeforeLoop);
-
- llvm::PHINode *stateLoop = llvm->builder.CreatePHI(tyNum, 2, "foldIt");
+ llvm::PHINode *stateLoop = llvm->builder.CreatePHI(rangeFrom->getType(), 2, "foldIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// * loop body
- ManagedScpPtr scopeLoop = fold.blocks.front();
- Value* elIn = compileGetElement(varIn, stateLoop);
- scopeLoop->bindArg(accum, move(varAccum));
- scopeLoop->bindArg(elIn, move(varEl));
- Value* accumNext = scopeLoop->compileExpression(scopeLoop->__body, *llvm);
+ CodeScope* scopeLoop = fold.blocks.front();
+ CompilePass::CodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
+ Value* elIn = it->get(stateLoop);
+ loopUnit->bindArg(accum, move(varAccum));
+ loopUnit->bindArg(elIn, move(varEl));
+ Value* accumNext = loopUnit->compile();
// * break checks, continue checks
if (flagHasSaturation)
{
- llvm::BasicBlock *blockChecks = llvm::BasicBlock::Create(llvm::getGlobalContext(), "checks", llvm->context.function);
+ llvm::BasicBlock *blockChecks = llvm::BasicBlock::Create(llvm::getGlobalContext(), "checks", function->raw);
Value* condSat = llvm->builder.CreateICmpNE(accumNext, valSat);
llvm->builder.CreateCondBr(condSat, blockChecks, blockAfterLoop);
llvm->builder.SetInsertPoint(blockChecks);
}
// * computing next iteration state
- Value *stateLoopNext = llvm->builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
+ Value *stateLoopNext = it->move(stateLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
stateLoop->addIncoming(stateLoopNext, llvm->builder.GetInsertBlock());
// * next iteration checks
- Value* condAfter = llvm->builder.CreateICmpSLE(stateLoopNext, rangeTo);
+ Value* condAfter = llvm->builder.CreateICmpNE(stateLoopNext, rangeTo);
llvm->builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accum;
}
llvm::Value*
-Instructions::compileIf(const Expression& exprIf, const std::string& ident)
+Instructions::compileIf(const Expression& exprIf, const std::string& hintRetVar)
{
- #define NAME(x) (ident.empty()? x : ident)
+ EXPAND_CONTEXT
//initialization:
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
- llvm::BasicBlock *blockAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", llvm->context.function);
- llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", llvm->context.function);
- llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", llvm->context.function);
+ 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->compileExpression(condExpr, *llvm);
+ llvm::Value* cond = scope->process(condExpr);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockTrue);
- ManagedScpPtr scopeTrue = exprIf.blocks.front();
- llvm::Value* resultTrue = scopeTrue->compileExpression(scopeTrue->__body, *llvm);
+ CodeScope* scopeTrue = exprIf.blocks.front();
+ llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
- ManagedScpPtr scopeFalse = exprIf.blocks.back();
- llvm::Value* resultFalse = scopeFalse->compileExpression(scopeFalse->__body, *llvm);
+ CodeScope* scopeFalse = exprIf.blocks.back();
+ llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
llvm::PHINode *ret = builder.CreatePHI(tyNum, 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
llvm::Value*
Instructions::compileConstantArray(const Expression &expr, const std::string& hintRetVar) {
- const int& __size = expr.getOperands().size();
+ EXPAND_CONTEXT
+
+ const size_t& __size = expr.getOperands().size();
const Expression& __data = expr;
- ArrayType* typList = (ArrayType*) (TypeAnnotation(tag_array, TypePrimitive::i32, __size).toLLVMType());
- Type*typI32 = TypeAnnotation(TypePrimitive::i32).toLLVMType();
+ ArrayType* typList = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I32, __size))));
+ Type*typI32 = llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::I32)));
std::vector<Constant *> list;
list.reserve(__size);
const std::vector<Expression> operands = __data.getOperands();
std::transform(operands.begin(), operands.end(), std::inserter(list, list.begin()),
[typI32](const Expression& e){return ConstantInt::get(typI32, e.getValueDouble());});
Value* listSource = ConstantArray::get(typList, ArrayRef<Constant*>(list));
/*
Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
*/
return listSource;
-}
\ No newline at end of file
+}
+
+llvm::Value*
+Instructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar)
+{
+ EXPAND_CONTEXT
+
+ size_t size = data.size();
+ Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm::getGlobalContext()));
+ //ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
+
+ /*
+ std::vector<Constant *> chars;
+ chars.reserve(size+1);
+
+ for (size_t i=0; i< size; ++i){
+ chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
+ }
+ chars[size] = ConstantInt::get(typI8, 0);
+ */
+
+ Value* rawData = ConstantDataArray::getString(llvm::getGlobalContext(), data);
+ Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 1, false));
+ llvm->builder.CreateStore(rawData, rawPtrData);
+ return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
+}
+
+
+
+template<ImplementationType I>
+class IteratorForward;
+
+template<>
+class IteratorForward<ON_THE_FLY> : public Iterator {
+private:
+ LLVMLayer* llvm;
+ const xreate::Symbol current;
+ const Symbol source;
+ const ImplementationLinkedList linkedlist;
+ CodeScope* const sourceScope;
+ //TODO initialize ans mark as const (three fields)
+ CompilePass::CodeScopeUnit* sourceUnit;
+ CompilePass::FunctionUnit* function;
+ const Expression& sourceDecl;
+ CompilePass::Context context;
+ llvm::Type* sourceRawType =nullptr;
+
+public:
+ IteratorForward(CompilePass::Context ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
+ : context(ctx), source(implementation.source), current(s), sourceScope(source.scope), sourceDecl(CodeScope::findDeclaration(source)),
+ linkedlist(source), sourceUnit(new CompilePass::CodeScopeUnit(source.scope, ctx.function, ctx.pass)), llvm(ctx.pass->man->llvm)
+ {
+ }
+
+ llvm::Value* begin() {
+ switch(sourceDecl.op) {
+ case xreate::Operator::LIST:
+ {
+ sourceRawType = Type::getInt32Ty(llvm::getGlobalContext());
+ return ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 0);
+ };
+
+ case xreate::Operator::LIST_RANGE:{
+ assert(sourceDecl.operands.size()==2);
+
+ llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
+ sourceRawType = result->getType();
+
+ return result;
+ };
+ }
+
+ if (linkedlist){
+ llvm::Value* result = sourceUnit->process(sourceDecl);
+ sourceRawType = result->getType();
+ return result;
+ }
+
+ assert(false);
+ }
+
+ llvm::Value* end(){
+ switch(sourceDecl.op) {
+ case xreate::Operator::LIST: {
+ size_t idLast = sourceDecl.operands.size() - 1;
+ return ConstantInt::get(sourceRawType, idLast);
+ }
+
+ case xreate::Operator::LIST_RANGE: {
+ assert(sourceDecl.operands.size() == 2);
+ return sourceUnit->process(sourceDecl.operands.at(1));
+ };
+ }
+
+ //return null pointer
+ if (linkedlist){
+ return ConstantPointerNull::getNullValue(sourceRawType);
+ }
+ }
+
+ llvm::Value* get(Value* index,const std::string& hintRetVar="") override{
+ const Expression& currentDecl = CodeScope::findDeclaration(current);
+
+ switch (currentDecl.op) {
+ case xreate::Operator::LIST: {
+ llvm::Value* currentValue = sourceUnit->process(currentDecl); //TODO re check is it right scope(source) to compilation currentDecl
+ return Instructions(context).compileArrayIndex(current, vector<Value *>{index});
+ };
+
+ case xreate::Operator::LIST_RANGE: {
+ return index;
+ };
+
+ case xreate::Operator::MAP: {
+ assert(currentDecl.getOperands().size()==1);
+ assert(currentDecl.bindings.size());
+ assert(currentDecl.blocks.size());
+
+ CodeScope* scopeLoop = currentDecl.blocks.front();
+ const std::string& varIn = currentDecl.getOperands()[0].getValueString();
+ std::string varEl = currentDecl.bindings[0];
+
+ const Symbol& symbIn = current.scope->findSymbol(varIn);
+ auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
+
+ Value* elIn = it->get(index, varEl);
+ CompilePass::CodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
+ unitLoop->bindArg(elIn, std::move(varEl));
+ return unitLoop->compile();
+ }
+
+ case xreate::Operator::NONE: {
+ assert(currentDecl.__state==Expression::IDENT);
+ const Symbol& symbIn = current.scope->findSymbol(currentDecl.getValueString());
+ auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
+ return it->get(index);
+ };
+ }
+
+ if (linkedlist){
+ return index;
+ }
+ }
+
+ llvm::Value* move(Value* index, const std::string& hintRetVar) override{
+ switch(sourceDecl.op)
+ {
+ case xreate::Operator::LIST:
+ case xreate::Operator::LIST_RANGE:
+ return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 1), hintRetVar);
+ }
+
+ if (linkedlist){
+ ExpandedType tySource = llvm->ast->expandType(sourceScope->findDefinition(source));
+ assert(tySource->__operator == TypeOperator::ARRAY && "Linked list implementation has to have ARRAY type");
+ assert(tySource->__operands.size());
+
+ return Instructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
+ }
+ }
+};
+
+Iterator*
+Iterator::create(CompilePass::Context context, const Symbol& var){
+
+ const Implementation& data = Query::queryImplementation(var);
+
+ switch(data.impl){
+ case ON_THE_FLY:
+ return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
+
+ default: assert(true);
+ }
+}
diff --git a/cpp/src/instructions/instr-containers.h b/cpp/src/instructions/instr-containers.h
index bbb89fb..be660d1 100644
--- a/cpp/src/instructions/instr-containers.h
+++ b/cpp/src/instructions/instr-containers.h
@@ -1,76 +1,85 @@
#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H
#include "llvmlayer.h"
#include "ast.h"
#include <llvm/IR/Value.h>
#include <vector>
+#include "pass/compilepass.h"
namespace xreate {
namespace containers {
+class Iterator{
+public :
+ virtual llvm::Value* begin() =0;
+ virtual llvm::Value* end() = 0;
+ virtual llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") = 0;
+ virtual llvm::Value* move(llvm::Value* index, const std::string& hintRetVar="")=0;
+ virtual ~Iterator(){};
+
+ static Iterator* create(CompilePass::Context context, const Symbol& var);
+};
+
class Instructions {
public:
- Instructions(CodeScope *current, LLVMLayer* layer);
- llvm::Value* compileIndex(const Symbol& dataSymbol, std::vector<llvm::Value*> indexes, std::string ident="");
- llvm::Value* compileGetElement(std::string varIn, llvm::Value* stateLoop, std::string ident="");
-
+ Instructions(CompilePass::Context ctx);
+ llvm::Value* compileArrayIndex(const Symbol &dataSymbol, std::vector<llvm::Value *> indexes, std::string ident = "");
+ llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
- llvm::Value* compileMapArray(const Expression &expr, const std::string hintRetVar="");
+ llvm::Value*compileMapSolid(const Expression &expr, const std::string hintRetVar = "");
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
-
- llvm::Value *compileConstantArray(const Expression &expr, const std::string& hintRetVar="");
+ llvm::Value* compileConstantStringAsPChar(const string &data, const std::string& hintRetVar);
+ llvm::Value* compileConstantArray(const Expression &expr, const std::string& hintRetVar="");
private:
- CodeScope* scope;
- LLVMLayer* llvm;
-
+ CompilePass::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif //CODEINSTRUCTIONS_H
/*
template<Operator Instruction>
struct InstructionClasses {};
template<>
struct InstructionClasses<Operator::LIST> {
typedef InstructionList Impl;
};
template<>
struct InstructionClasses<Operator::MAP> {
typedef InstructionMap Impl;
};
template<Operator Instruction>
class CodeInstruction: public InstructionClasses<Instruction>::Impl
{
typedef typename InstructionClasses<Instruction>::Impl InstructionImpl;
public:
CodeInstruction(CodeScope* parent)
: InstructionImpl(parent)
{}
llvm::Value *
compileExpression(const Expression &expr, LLVMLayer &l, const std::string * const hintRetVar)
{
if (expr.op == Instruction)
return InstructionImpl::compileDefault(expr, l, hintRetVar);
return CodeScope::compileExpression(expr, l, hintRetVar);
}
};
}
-*/
\ No newline at end of file
+*/
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 192ec38..47121d3 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,15 +1,229 @@
+#include "ast.h"
#include "llvmlayer.h"
+#include "ExternLayer.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/Support/TargetSelect.h"
+#include <iostream>
using namespace llvm;
using namespace xreate;
+using namespace std;
-LLVMLayer::LLVMLayer()
- :builder(getGlobalContext())
+LLVMLayer::LLVMLayer(AST* root)
+ :builder(getGlobalContext()), ast(root)
{
+ module = new llvm::Module(root->getModuleName(), llvm::getGlobalContext());
+ layerExtern = new ExternLayer(this);
+ layerExtern->init(root);
+}
+
+void*
+LLVMLayer::getFunctionPointer(llvm::Function* function){
+ uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
+ return (void*) entryAddr;
+}
+
+void
+LLVMLayer::initJit(){
+ std::string ErrStr;
+ LLVMInitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmPrinter();
+
+ llvm::EngineBuilder builder((std::unique_ptr<llvm::Module>(module)));
+ jit = builder
+ .setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&ErrStr)
+ .setVerifyModules(true)
+ .create();
+}
+
+void
+LLVMLayer::print(){
+ llvm::PassManager<llvm::Module> PM;
+ PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
+ PM.run(*module);
}
void
LLVMLayer::moveToGarbage(void *o)
{
__garbage.push_back(o);
}
+
+llvm::Type*
+LLVMLayer::
+toLLVMType(const ExpandedType& ty) const {
+ std::map<int, llvm::StructType*> empty;
+ return toLLVMType(ty, empty);
+}
+
+llvm::Type*
+LLVMLayer::
+toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const
+{
+ TypeAnnotation t = ty;
+ switch (t.__operator)
+ {
+ case TypeOperator::ARRAY:
+ {
+ assert(t.__operands.size()==1);
+
+ TypeAnnotation elTy = t.__operands.at(0);
+ return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
+ }
+
+ case TypeOperator::STRUCT:
+ case TypeOperator::TUPLE:
+ {
+ assert(t.__operands.size());
+
+ std::vector<llvm::Type*> pack_;
+ pack_.reserve(t.__operands.size());
+
+ std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
+ [this, &conjuctions](const TypeAnnotation& t){
+ return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
+ });
+
+ llvm::ArrayRef<llvm::Type*> pack(pack_);
+
+ //process recursive types:
+ if (conjuctions.count(t.conjuctionId)) {
+ auto result = conjuctions[t.conjuctionId];
+ result->setBody(pack, false);
+
+ return result;
+ }
+
+ return llvm::StructType::get(llvm::getGlobalContext(), pack, false);
+ };
+
+ case TypeOperator::LINK: {
+ llvm::StructType* conjuction = llvm::StructType::create(llvm::getGlobalContext());
+ int id = t.conjuctionId;
+
+ conjuctions.emplace(id, conjuction);
+ return conjuction;
+ };
+
+ case TypeOperator::CALL:
+ {
+ assert(false);
+ };
+
+ case TypeOperator::CUSTOM:
+ {
+ //Look in extern types
+
+ clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
+ return layerExtern->toLLVMType(qt);
+ };
+
+ case TypeOperator::NONE: {
+ switch (t.__value) {
+ case TypePrimitive::Bool:
+ return llvm::Type::getInt1Ty(llvm::getGlobalContext());
+
+ case TypePrimitive::I32:
+ case TypePrimitive::Int:
+ case TypePrimitive::Num:
+ return llvm::Type::getInt32Ty(llvm::getGlobalContext());
+
+ case TypePrimitive::I8:
+ return llvm::Type::getInt8Ty(llvm::getGlobalContext());
+
+ case TypePrimitive::Float:
+ return llvm::Type::getDoubleTy(llvm::getGlobalContext());
+
+ case TypePrimitive::String:
+ return llvm::Type::getInt8PtrTy(llvm::getGlobalContext());
+
+ default:
+ assert(false);
+ }
+ }
+
+ default:
+ assert(false);
+ }
+
+ assert(false);
+ return nullptr;
+}
+
+void
+LLVMLayer::initExceptionsSupport(){
+ Type* typInt8Ptr = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
+
+ if (!module->getFunction("__cxa_throw")) {
+ std::vector<Type*> fThrowSignature{typInt8Ptr, typInt8Ptr, typInt8Ptr};
+
+ FunctionType* tyFThrow = FunctionType::get(
+ /*Result=*/Type::getVoidTy(module->getContext()),
+ /*Params=*/fThrowSignature,
+ /*isVarArg=*/false);
+
+ llvm::Function::Create(
+ /*Type=*/tyFThrow,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"__cxa_throw", module); // (external, no body)
+ }
+
+ if (!module->getFunction("__cxa_allocate_exception")) {
+ std::vector<Type*>fAllocateSignature{IntegerType::get(module->getContext(), 64)};
+
+ FunctionType* tyFAllocate = FunctionType::get(
+ /*Result=*/typInt8Ptr,
+ /*Params=*/fAllocateSignature,
+ /*isVarArg=*/false);
+
+ llvm::Function::Create(
+ /*Type=*/tyFAllocate,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"__cxa_allocate_exception", module); // (external, no body)
+ }
+}
+
+bool TypeUtils::isStruct(const ExpandedType& ty){
+ const TypeAnnotation& t = ty.get();
+
+ if (t.__operator==TypeOperator::STRUCT) {
+ return true;
+ }
+
+ if (t.__operator != TypeOperator::CUSTOM) {
+ return false;
+ }
+
+ clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
+ const clang::Type * raw = tqual.getTypePtr();
+
+ // TODO skip ALL the pointers until non-pointer type found
+ if (raw->isStructureType()) return true;
+ if (!raw->isAnyPointerType()) return false;
+
+ const clang::PointerType* tPtr = raw->getAs<clang::PointerType>();
+ clang::QualType pointee = raw->getPointeeType();
+ const clang::Type * pointeeRaw = pointee.getTypePtr();
+ return pointee->isStructureType();
+}
+
+
+bool TypeUtils::isPointer(const ExpandedType &ty) {
+ if (ty.get().__operator != TypeOperator::CUSTOM) return false;
+
+ clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
+ return llvm->layerExtern->isPointer(qt);
+}
+
+
+std::vector<std::string>
+TypeUtils::getStructFields(const ExpandedType &t) {
+ return (t.get().__operator == TypeOperator::STRUCT)
+ ? t.get().fields
+ : llvm->layerExtern->getStructFields(
+ llvm->layerExtern->lookupType(t.get().__valueCustom));
+}
+
+
diff --git a/cpp/src/llvmlayer.h b/cpp/src/llvmlayer.h
index 937143c..3079d28 100644
--- a/cpp/src/llvmlayer.h
+++ b/cpp/src/llvmlayer.h
@@ -1,38 +1,56 @@
#ifndef LLVMLAYER_H
#define LLVMLAYER_H
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"
-//#include "ast.h"
+
namespace xreate {
class AST;
+ class ExternLayer;
+ class TypeAnnotation;
class LLVMLayer {
public:
- LLVMLayer();
+ LLVMLayer(AST* rootAST);
- AST *ast;
- llvm::Module *module;
+ AST *ast = 0;
+ ExternLayer *layerExtern =0;
+ llvm::Module *module = 0;
+ llvm::ExecutionEngine* jit= 0;
llvm::IRBuilder<> builder;
- struct {
- llvm::Function* function = 0;
- } context;
-
void moveToGarbage(void *o);
- llvm::Value *compile() const;
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
+ void print();
+ void* getFunctionPointer(llvm::Function* function);
+ void initJit();
+ void initExceptionsSupport();
private:
+ llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
std::vector<void *> __garbage;
};
+
+ struct TypeUtils {
+ bool isStruct(const Expanded<TypeAnnotation>& ty);
+ bool isPointer(const Expanded<TypeAnnotation>& ty);
+ std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
+
+ TypeUtils(LLVMLayer*llvmlayer)
+ : llvm(llvmlayer){}
+
+ private:
+ LLVMLayer* llvm;
+ };
}
#endif // LLVMLAYER_H
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index a729a75..8ca4dc2 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,90 +1,15 @@
#include "abstractpass.h"
#include "attachments.h"
+#include "passmanager.h"
+
using namespace std;
namespace xreate {
- void
- AbstractPass::process(ManagedRulePtr rule)
- {}
-
- void
- AbstractPass::process(ManagedFnPtr function) {
- PassContext context;
- context.function = function;
-
- process(function->getEntryScope(), context);
- }
-
- void
- AbstractPass::process(CodeScope *scope, PassContext context) {
- context.scope = scope;
- process(scope->__body, context);
- }
-
- void
- AbstractPass::process(const Expression& expression, PassContext context, const std::string& varDecl){
- switch (expression.__state) {
- case Expression::COMPOUND:
- for (const Expression &op: expression.getOperands()) {
- process(op, context);
- }
-
- assert(expression.op != Operator::MAP || expression.op == Operator::MAP && expression.blocks.size());
- for (ManagedScpPtr scope: expression.blocks) {
- process(&*scope, context);
- }
-
- /*
- if (expression.op == Operator::CALL) {
- const std::string &calleeName = expression.getValueString();
- ManagedFnPtr callee = root->findFunction(calleeName);
- }
- */
- break;
-
- case Expression::IDENT:
- assert(context.scope);
-
- string ident = expression.getValueString();
- const Symbol& symbol = context.scope->findSymbol(ident, *man->llvm);
-
- if (SymbolAttachments::get<IsDeclVisited> (symbol, false)) {break;}
- SymbolAttachments::put<IsDeclVisited> (symbol, true);
-
- PassContext context2 = context;
- context2.scope = symbol.scope;
- if (CodeScope::hasDeclaration(symbol)) {
- process(CodeScope::findDeclaration(symbol), context2, ident);
- }
-
- break;
- }
- }
-
- void
- AbstractPass::processFnCall(ManagedFnPtr function, PassContext context)
- {
- }
-
- void
- AbstractPass::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;
- }
- }
- void AbstractPass::finish()
+ void AbstractPassBase::finish()
{}
- AbstractPass::AbstractPass(PassManager *manager)
+ AbstractPassBase::AbstractPassBase(PassManager *manager)
: man(manager) {
}
-}
\ No newline at end of file
+}
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index a49d1a1..89e74ec 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,38 +1,121 @@
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
-
+#include "ast.h"
#include "passmanager.h"
+#include<iostream>
+using namespace std;
namespace xreate
{
struct PassContext
{
CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext()
{}
+ PassContext&& updateScope(CodeScope* scopeNew) {
+ PassContext context2{*this};
+ context2.scope = scopeNew;
+ return std::move(context2);
+ }
+
~PassContext(){}
};
- class AbstractPass
- {
+ class PassManager;
+
+ class AbstractPassBase {
public:
- AbstractPass(PassManager* man);
- virtual void run();
+ AbstractPassBase(PassManager* manager);
+ virtual void run()=0;
virtual void finish();
- virtual void processFnCall(ManagedFnPtr function, PassContext context);
- virtual void process(ManagedFnPtr function);
- virtual void process(ManagedRulePtr rule);
- virtual void process(CodeScope* scope, PassContext context);
- virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
-
- protected:
PassManager* man;
};
+
+ template<class Output>
+ class AbstractPass: public AbstractPassBase {
+ private:
+ std::set<Symbol> __visitedSymbols;
+
+ public:
+ AbstractPass(PassManager* manager): AbstractPassBase(manager) {}
+
+ //NOTE implement processFnCall
+ virtual void processFnCall(ManagedFnPtr function, PassContext context)
+ {}
+
+ virtual void process(ManagedRulePtr rule)
+ {}
+
+ virtual Output process(ManagedFnPtr function){
+ PassContext context;
+ context.function = function;
+
+ return process(function->getEntryScope(), context);
+ }
+
+ virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){
+ context.scope = scope;
+ return process(scope->__body, context);
+ }
+
+ virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){
+ switch (expression.__state) {
+ case Expression::COMPOUND:
+ for (const Expression &op: expression.getOperands()) {
+ process(op, context);
+ }
+
+ assert(expression.op != Operator::MAP || expression.op == Operator::MAP && expression.blocks.size());
+ for (CodeScope* scope: expression.blocks) {
+ process(scope, context);
+ }
+
+ /*
+ if (expression.op == Operator::CALL) {
+ const std::string &calleeName = expression.getValueString();
+ ManagedFnPtr callee = root->findFunction(calleeName);
+ }
+ */
+ break;
+
+ case Expression::IDENT:
+ assert(context.scope);
+
+ std::string ident = expression.getValueString();
+ const Symbol& symbol = context.scope->findSymbol(ident);
+
+ if (__visitedSymbols.count(symbol)) {break;}
+ __visitedSymbols.insert(symbol);
+
+ PassContext context2 = context;
+ context2.scope = symbol.scope;
+ if (CodeScope::hasDeclaration(symbol)) {
+ process(CodeScope::findDeclaration(symbol), context2, ident);
+ }
+
+ break;
+ }
+ }
+
+ void run() {
+ ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
+ while (rule.isValid()) {
+ process(rule);
+ ++rule;
+ }
+
+ ManagedFnPtr f = man->root->begin<Function>();
+ while (f.isValid()) {
+ process(f);
+ ++f;
+ }
+ }
+ };
}
-#endif
\ No newline at end of file
+#endif
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
new file mode 100644
index 0000000..e374bc8
--- /dev/null
+++ b/cpp/src/pass/compilepass.cpp
@@ -0,0 +1,449 @@
+#include "compilepass.h"
+#include "clasplayer.h"
+#include <ast.h>
+#include <iostream>
+#include "query/containers.h"
+#include "instructions/instr-containers.h"
+#include "ExternLayer.h"
+
+using namespace std;
+using namespace xreate;
+using namespace llvm;
+
+CompilePass::CodeScopeUnit::CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
+ : scope(codeScope), pass(compilePass), function(f)
+{}
+
+void
+CompilePass::CodeScopeUnit::bindArg(llvm::Value* var, std::string&& name)
+{
+ assert(scope->__vartable.count(name));
+ VID id = scope->__vartable.at(name);
+ __rawVars[id] = var;
+}
+
+llvm::Value*
+CompilePass::CodeScopeUnit::convertType(llvm::Value* source, llvm::Type* tyTarget){
+ LLVMLayer* llvm = pass->man->llvm;
+
+ if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
+ {
+ llvm::IntegerType* tyTargetInt = llvm::dyn_cast<IntegerType>(tyTarget);
+ llvm::IntegerType* tySourceInt = llvm::dyn_cast<IntegerType>(source->getType());
+
+ if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
+ return llvm->builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
+ }
+
+ if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
+ return llvm->builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
+ }
+ }
+
+ assert(false && "no automatic type conversion possible");
+}
+
+llvm::Value*
+CompilePass::CodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
+#define VARNAME(x) (hintVarDecl.empty()? x: hintVarDecl)
+ llvm::Value *left; llvm::Value *right;
+ LLVMLayer& l = *pass->man->llvm;
+ CompilePass::Context context{function, this, pass};
+ containers::Instructions instructions = containers::Instructions(context);
+
+ switch (expr.op) {
+ case Operator::ADD:
+ case Operator::SUB:
+ case Operator::MUL:
+ case Operator::DIV:
+ case Operator::EQU:
+ case Operator::LSS:
+ case Operator::GTR:
+ assert(expr.__state == Expression::COMPOUND);
+ assert(expr.operands.size() == 2);
+
+ left = process(expr.operands[0]);
+ right = process(expr.operands[1]);
+
+ if (left->getType()!= right->getType()) {
+ right = convertType(right, left->getType());
+ }
+ break;
+
+ default:;
+ }
+
+ switch (expr.op) {
+ case Operator::ADD:
+ return l.builder.CreateAdd(left, right, VARNAME("tmp_add"));
+ break;
+
+ case Operator::SUB:
+ return l.builder.CreateSub(left, right, VARNAME("tmp_sub"));
+ break;
+
+ case Operator::MUL:
+ return l.builder.CreateMul(left, right, VARNAME("tmp_mul"));
+ break;
+
+ case Operator::DIV:
+ return l.builder.CreateSDiv(left, right, VARNAME("tmp_div"));
+ break;
+
+ case Operator::EQU:
+ left->dump();
+ right->dump();
+ return l.builder.CreateICmpEQ(left, right, VARNAME("tmp_equ"));
+ break;
+
+ case Operator::LSS:
+ return l.builder.CreateICmpSLT(left, right, VARNAME("tmp_lss"));
+ break;
+
+ case Operator::GTR:
+ return l.builder.CreateICmpSGT(left, right, VARNAME("tmp_gtr"));
+ break;
+
+ case Operator::NEG:
+ left = process(expr.operands[0]);
+ return l.builder.CreateNeg(left, VARNAME("tmp_neg"));
+ break;
+
+ case Operator::CALL: {
+ assert(expr.__state == Expression::COMPOUND);
+
+ std::string fname = expr.getValueString();
+
+
+ std::vector<llvm::Value *> args;
+ args.reserve(expr.operands.size());
+
+ std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
+ [this](const Expression &operand) {
+ return process(operand);
+ }
+ );
+
+ FunctionUnit* calleeUnit = pass->getFunctionUnit(string(fname));
+
+ // external function
+ if (!calleeUnit) {
+ llvm::Function* external = pass->man->llvm->layerExtern->lookupFunction(fname);
+ return l.builder.CreateCall(external, args, hintVarDecl);
+ }
+
+ if (calleeUnit->isInline()) {
+ return calleeUnit->compileInline(move(args), this->function);
+ }
+
+ llvm::BasicBlock* blockPrev = pass->man->llvm->builder.GetInsertBlock();
+ llvm::Value* callee = calleeUnit->compile();
+ pass->man->llvm->builder.SetInsertPoint(blockPrev);
+ return l.builder.CreateCall(callee, args, hintVarDecl);
+ }
+
+ case Operator::IF:
+ {
+ return instructions.compileIf(expr, hintVarDecl);
+ }
+
+ case Operator::LIST:
+ {
+ return instructions.compileConstantArray(expr, hintVarDecl);
+ };
+
+ case Operator::LIST_RANGE:
+ {
+ assert(false); //no compilation phase for a range list
+ // return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
+ };
+
+ case Operator::LIST_NAMED:
+ {
+ typedef Expanded<TypeAnnotation> ExpandedType;
+
+ ExpandedType tyRaw = l.ast->expandType(expr.type);
+
+ const std::vector<string> fields = (tyRaw.get().__operator == TypeOperator::CUSTOM)?
+ l.layerExtern->getStructFields(l.layerExtern->lookupType(tyRaw.get().__valueCustom))
+ : tyRaw.get().fields;
+
+ std::map<std::string, size_t> indexFields;
+ for(size_t i=0, size = fields.size(); i<size; ++i){
+ indexFields.emplace(fields[i], i);
+ }
+
+ llvm::StructType* tyRecord = llvm::cast<llvm::StructType>(l.toLLVMType(tyRaw));
+ llvm::Value* record = llvm::UndefValue::get(tyRecord);
+
+ for (int i=0; i<expr.operands.size(); ++i){
+ const Expression& operand = expr.operands.at(i);
+ unsigned int fieldId = indexFields.at(expr.bindings.at(i));
+
+ llvm::Value* result = 0;
+
+ if (operand.isNone()){
+ llvm::Type* tyNullField = tyRecord->getElementType(fieldId);
+ result = llvm::UndefValue::get(tyNullField);
+
+ } else {
+ result = process(operand);
+ }
+
+ assert (result);
+ record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
+ }
+
+ return record;
+ };
+
+
+
+ case Operator::MAP:
+ {
+ assert(expr.blocks.size());
+ return instructions.compileMapSolid(expr, VARNAME("map"));
+ };
+
+ case Operator::FOLD:
+ {
+ return instructions.compileFold(expr, VARNAME("fold"));
+ };
+
+ case Operator::INDEX:
+ {
+ //TODO allow multiindex
+ assert(expr.operands.size()==1);
+ const std::string &ident = expr.getValueString();
+ Symbol s = scope->findSymbol(ident);
+ const TypeAnnotation& t = s.scope->findDefinition(s);
+ const ExpandedType& t2 = pass->man->root->expandType(t);
+
+ switch (t2.get().__operator)
+ {
+ case TypeOperator::STRUCT: case TypeOperator::CUSTOM:
+ {
+ Expression idx = expr.operands.at(0);
+ assert(idx.__state == Expression::STRING);
+ std::string idxField = idx.getValueString();
+
+ llvm::Value* aggr = compileSymbol(s, ident);
+ return instructions.compileStructIndex(aggr, t2, idxField);
+ };
+
+ case TypeOperator::ARRAY: {
+ std::vector<llvm::Value*> indexes;
+ std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
+ [this] (const Expression& op){return process(op);}
+ );
+
+ return instructions.compileArrayIndex(s, indexes, VARNAME(string("el_") + ident));
+ };
+
+ default:
+ assert(false);
+ }
+ };
+
+
+ case Operator::NONE:
+ assert(expr.__state != Expression::COMPOUND);
+
+ switch (expr.__state) {
+ case Expression::IDENT: {
+ const std::string &ident = expr.getValueString();
+ Symbol s = scope->findSymbol(ident);
+ return compileSymbol(s, ident);
+ }
+
+ case Expression::NUMBER: {
+ int literal = expr.getValueDouble();
+ return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
+ }
+
+ case Expression::STRING: {
+ return instructions.compileConstantStringAsPChar(expr.getValueString(), hintVarDecl);
+ };
+
+
+ };
+
+ break;
+
+ }
+
+ assert(false);
+ return 0;
+}
+
+llvm::Value*
+CompilePass::CodeScopeUnit::compile(const std::string& hintBlockDecl){
+ if (raw != nullptr) return raw;
+
+
+ if (!hintBlockDecl.empty()) {
+ llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
+ pass->man->llvm->builder.SetInsertPoint(block);
+ }
+
+ raw = process(scope->__body);
+ return raw;
+}
+
+llvm::Value*
+CompilePass::CodeScopeUnit::compileSymbol(const Symbol& s, std::string hintRetVar)
+{
+ CodeScope* scope = s.scope;
+ CodeScopeUnit* self = function->getScopeUnit(scope);
+
+ if (self->__rawVars.count(s.identifier)) {
+ return self->__rawVars[s.identifier];
+ }
+
+ return self->__rawVars[s.identifier] = self->process(scope->findDeclaration(s), hintRetVar);
+}
+
+bool
+CompilePass::FunctionUnit::isInline(){
+ Symbol ret = Symbol{0, function->__entry};
+ bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
+
+ return flagOnTheFly;
+}
+
+llvm::Function*
+CompilePass::FunctionUnit::compile(){
+ if (raw != nullptr) return raw;
+
+ std::vector<llvm::Type *> types;
+ LLVMLayer* llvm = pass->man->llvm;
+ CodeScope* entry = function->__entry;
+
+ std::transform(entry->__args.begin(), entry->__args.end(), std::inserter(types, types.end()),
+ [this, llvm, entry](const std::string &arg)->llvm::Type* {
+ assert(entry->__vartable.count(arg));
+ VID argid = entry->__vartable.at(arg);
+ assert(entry->__definitions.count(argid));
+ return llvm->toLLVMType(pass->man->root->expandType(entry->__definitions.at(argid)));
+ });
+
+ llvm::FunctionType *ft = llvm::FunctionType::get(llvm->toLLVMType(pass->man->root->expandType(entry->__definitions[0])), types, false);
+ raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(function->__name, ft));
+
+ CodeScopeUnit* entryCompilation = getScopeUnit(entry);
+ llvm::Function::arg_iterator fargsI = raw->arg_begin();
+ for (std::string &arg : entry->__args) {
+ VID argid = entry->__vartable[arg];
+
+ entryCompilation->__rawVars[argid] = fargsI;
+ fargsI->setName(arg);
+ ++fargsI;
+ }
+
+ const std::string blockName = "entry";
+ llvm->builder.CreateRet(entryCompilation->compile(blockName));
+
+ llvm->moveToGarbage(ft);
+ return raw;
+}
+
+//TEST FunctionUnit::compileInline
+llvm::Value*
+CompilePass::FunctionUnit::compileInline(std::vector<llvm::Value *> &&args, CompilePass::FunctionUnit* outer){
+ CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
+ for(int i=0, size = args.size(); i<size; ++i) {
+ entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__args.at(i)));
+ }
+
+
+ return entryCompilation->compile();
+}
+
+CompilePass::CodeScopeUnit*
+CompilePass::FunctionUnit::getScopeUnit(CodeScope* scope){
+ if (!scopes.count(scope)){
+ CodeScopeUnit* unit = new CodeScopeUnit(scope, this, pass);
+ scopes.emplace(scope, std::unique_ptr<CodeScopeUnit>(unit));
+ }
+
+ return scopes.at(scope).get();
+}
+
+CompilePass::CodeScopeUnit*
+CompilePass::FunctionUnit::getEntry(){
+ return getScopeUnit(function->getEntryScope());
+}
+
+CompilePass::CodeScopeUnit*
+CompilePass::FunctionUnit::getScopeUnit(ManagedScpPtr scope){
+ return getScopeUnit(&*scope);
+}
+
+CompilePass::FunctionUnit*
+CompilePass::getFunctionUnit(const CompilePass::FunctionQuery& f){
+ ManagedFnPtr fkey = man->root->findFunction(f.name);
+
+ //external functions:
+ if (!fkey){
+ return nullptr;
+ }
+
+ if (!functions.count(&*fkey)){
+ functions.emplace(&*fkey, std::unique_ptr<FunctionUnit>(new FunctionUnit(fkey, this)));
+ }
+
+ return functions.at(&*fkey).get();
+}
+
+void
+CompilePass::run(){
+ //Find out main function;
+ ClaspLayer::ModelRange model = man->clasp->query(Config::get("function-entry"));
+ assert(model && "Error: No entry function found");
+ assert(model->first != model->second && "Error: Ambiguous entry function");
+
+ string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model->first->second));
+ FunctionUnit* unitMain = getFunctionUnit(move(nameMain));
+ entry = unitMain->compile();
+}
+
+llvm::Function*
+CompilePass::getEntryFunction(){
+ assert(entry);
+ return entry;
+}
+
+
+//CODESCOPE COMPILATION PHASE
+
+
+//FIND SYMBOL(compilation phase):
+ //if (!forceCompile)
+ //{
+ // return result;
+ //}
+
+ // //search in already compiled vars
+ //if (__rawVars.count(vId))
+ //{
+ // return result;
+ //}
+
+ //if (!__declarations.count(vId)) {
+ // //error: symbol is uncompiled scope arg
+ // assert(false);
+ //}
+
+ //const Expression& e = __declarations.at(vId);
+
+ //__rawVars[vId] = process(e, l, name);
+
+
+//FIND FUNCTION
+ //llvm::Function*
+ //CompilePass::findFunction(const std::string& name){
+ // ManagedFnPtr calleeFunc = man->root->findFunction(name);
+ // assert(calleeFunc.isValid());
+
+ // return nullptr;
+ //}
diff --git a/cpp/src/pass/compilepass.h b/cpp/src/pass/compilepass.h
new file mode 100644
index 0000000..a135d6c
--- /dev/null
+++ b/cpp/src/pass/compilepass.h
@@ -0,0 +1,82 @@
+#ifndef COMPILEPASS_H
+#define COMPILEPASS_H
+
+#include "abstractpass.h"
+#include "llvm/IR/Function.h"
+
+namespace xreate {
+
+
+
+class CompilePass : public AbstractPass<void>
+{
+public:
+
+ class CodeScopeUnit;
+ class FunctionUnit{
+ public:
+ FunctionUnit(ManagedFnPtr f, CompilePass* p)
+ : function(f), pass(p) {}
+
+ llvm::Value* compileInline(std::vector<llvm::Value*>&& args, CompilePass::FunctionUnit* outer);
+ bool isInline();
+ llvm::Function* compile();
+
+ CodeScopeUnit* getEntry();
+ CodeScopeUnit* getScopeUnit(CodeScope* scope);
+ CodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
+
+ ManagedFnPtr function;
+ llvm::Function* raw = nullptr;
+ private:
+ CompilePass* pass;
+ std::map<CodeScope*, std::unique_ptr<CodeScopeUnit>> scopes;
+ };
+
+ class CodeScopeUnit {
+ public:
+ CodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass);
+
+ void bindArg(llvm::Value* var, std::string&& name);
+ std::map<VID,llvm::Value*> __rawVars;
+
+ llvm::Value* compile(const std::string& hintBlockDecl="");
+ llvm::Value* compileSymbol(const Symbol& s, std::string hintRetVar="");
+ llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="");
+ CodeScope* scope;
+
+ private:
+ CompilePass* pass;
+ llvm::Value* raw = nullptr;
+ FunctionUnit* function;
+
+ llvm::Value* convertType(llvm::Value* source, llvm::Type* tyTarget);
+ };
+
+ struct Context{
+ FunctionUnit* function;
+ CodeScopeUnit* scope;
+ CompilePass* pass;
+ };
+
+ struct FunctionQuery{
+ FunctionQuery(std::string&& functionName): name(functionName) {}
+
+ std::string name;
+ };
+
+ CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
+ FunctionUnit* getFunctionUnit(const FunctionQuery& f);
+ void run() override;
+ llvm::Function* getEntryFunction();
+
+private:
+ std::map<Function*, std::unique_ptr<FunctionUnit>> functions;
+ llvm::Function* entry = 0;
+
+
+};
+
+}
+
+#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfgpass.cpp b/cpp/src/pass/dfgpass.cpp
index 3586b0b..9026b78 100644
--- a/cpp/src/pass/dfgpass.cpp
+++ b/cpp/src/pass/dfgpass.cpp
@@ -1,144 +1,152 @@
-#include <kimproxy.h>
#include "dfgpass.h"
#include "../passmanager.h"
using namespace xreate;
using namespace std;
DFGPass::DFGPass(PassManager* manager)
- : AbstractPass(manager)
+ : AbstractPass(manager), clasp(man->clasp)
{}
-
-SymbolPacked
-DFGPass::processExpression(const Expression& expression, PassContext context, const std::string& decl)
+SymbolPackedOptional
+DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
+ // write down adhoc expression tags:
+ if (expression.tags.size() && decl.length()) {
+ for (pair<std::string, Expression> tag: expression.tags) {
+ SymbolPacked nodeThis = clasp->pack(context.scope->findSymbol(decl), decl);
+ __context.graph.addTag(nodeThis, Expression(tag.second));
+ }
+ }
+
+ switch(expression.__state) {
+ case Expression::IDENT:
+ AbstractPass::process(expression, context, decl);
+
+ string ident = expression.getValueString();
+ const Symbol& identSymbol = context.scope->findSymbol(ident);
+
+ SymbolPacked nodeFrom = clasp->pack(identSymbol);
+ if (!decl.empty()) {
+ SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl));
+ __context.graph.addLink(move(nodeTo), move(nodeFrom), DFGConnection::ALIAS);
+ }
+
+ return nodeFrom;
+ }
+
switch(expression.op) {
case Operator::CALL: {
const string &name = expression.getValueString();
- ManagedFnPtr function = man->root->findFunction(name);
- CodeScope *scopeRemote = function->getEntryScope();
- std::vector<SymbolPacked> operands;
+
+ std::vector<SymbolPackedOptional> operands;
operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
- operands.push_back(processExpression(op, context));
+ operands.push_back(process(op, context));
}
- std::vector<SymbolPacked>::iterator op = operands.begin();
+ ManagedFnPtr function = man->root->findFunction(name);
+ if (!function) return boost::none;
+
+ // set calling relations:
+ CodeScope *scopeRemote = function->getEntryScope();
+ std::vector<SymbolPackedOptional>::iterator op = operands.begin();
for (const std::string &arg: scopeRemote->__args) {
- if (op->isValid()) {
- const Symbol &nodeRemote = scopeRemote->findSymbol(arg, *man->llvm, false);
- __context.graph.addLink(__context.graph.pack(nodeRemote), *op, DFGConnection::OPT);
+ if (*op) {
+ const Symbol &nodeRemote = scopeRemote->findSymbol(arg);
+ __context.graph.addLink(clasp->pack(nodeRemote), **op, DFGConnection::OPT);
}
++op;
}
- SymbolPacked ret = __context.graph.pack(Symbol{0, scopeRemote});
+ SymbolPacked ret = clasp->pack(Symbol{0, scopeRemote});
if (!decl.empty()) {
__context.graph.addLink(
- __context.graph.pack(
- context.scope->findSymbol(decl, *man->llvm, false)),
+ clasp->pack(
+ context.scope->findSymbol(decl)),
ret, DFGConnection::OPT);
}
return ret;
}
+ }
- default: {
- std::vector<SymbolPacked> operands;
-
- if (__schemes.count(expression.op)) {
- const Expression &scheme = __schemes.at(expression.op);
-
- operands.reserve(expression.getOperands().size());
- for (const Expression &op: expression.getOperands()) {
- operands.push_back(processExpression(op, context));
- }
-
- std::vector<SymbolPacked>::const_iterator arg = operands.begin();
- std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
+ std::vector<SymbolPackedOptional> operands;
- while (tag != scheme.getOperands().end()) {
- if (arg->isValid() && tag->__state != Expression::INVALID) {
- __context.graph.addTag(*arg, Expression(*tag));
- }
+ if (__signatures.count(expression.op)) {
+ const Expression &scheme = __signatures.at(expression.op);
- ++arg; ++tag;
- }
+ operands.reserve(expression.getOperands().size());
+ for (const Expression &op: expression.getOperands()) {
+ operands.push_back(process(op, context));
+ }
- Expression retTag = *scheme.getOperands().begin();
- if (retTag.__state != Expression::INVALID) {
- assert(!decl.empty());
- SymbolPacked pdecl = __context.graph.pack(context.scope->findSymbol(decl, *man->llvm, false));
- __context.graph.addTag(pdecl, move(retTag));
- }
- }
+ std::vector<SymbolPackedOptional>::const_iterator arg = operands.begin();
+ std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
- // adhoc for MAP case, TODO reorganize code in more clear manner
- if (expression.op == Operator::MAP) {
- SymbolPacked nodeFrom;
+ while (tag != scheme.getOperands().end()) {
+ if (*arg && tag->__state != Expression::INVALID) {
+ __context.graph.addTag(**arg, Expression(*tag));
+ }
- if (operands.size()) {
- nodeFrom = operands.at(0);
- } else {
- nodeFrom = processExpression(expression.getOperands().at(0), context);
- }
+ ++arg; ++tag;
+ }
- assert(!decl.empty());
- SymbolPacked nodeTo = __context.graph.pack(context.scope->findSymbol(decl, *man->llvm, false));
- __context.graph.addLink(move(nodeTo), move(nodeFrom), DFGConnection::PROTO);
- }
- }
+ Expression retTag = *scheme.getOperands().begin();
+ if (retTag.__state != Expression::INVALID) {
+ assert(!decl.empty());
+ SymbolPacked pdecl = clasp->pack(context.scope->findSymbol(decl));
+ __context.graph.addTag(pdecl, move(retTag));
+ }
+ }
- }
+ // adhoc for MAP case, TODO reorganize code in more clear manner
+ if (expression.op == Operator::MAP) {
+ SymbolPackedOptional nodeFrom;
- switch(expression.__state) {
- case Expression::IDENT:
- AbstractPass::process(expression, context, decl);
+ if (operands.size()) {
+ nodeFrom = operands.at(0);
+ } else {
+ nodeFrom = process(expression.getOperands().at(0), context);
+ }
- string ident = expression.getValueString();
- const Symbol& identSymbol = context.scope->findSymbol(ident, *man->llvm);
+ assert(!decl.empty());
+ SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl));
+ __context.graph.addLink(move(nodeTo), move(*nodeFrom), DFGConnection::PROTO);
+ }
- SymbolPacked nodeFrom = __context.graph.pack(identSymbol);
- if (!decl.empty()) {
- SymbolPacked nodeTo = __context.graph.pack(context.scope->findSymbol(decl, *man->llvm));
- __context.graph.addLink(move(nodeTo), move(nodeFrom), DFGConnection::STRONG);
- }
+ if (__signatures.count(expression.op) || expression.op == Operator::MAP) {
+ for (CodeScope* scope: expression.blocks) {
+ AbstractPass::process(scope, context);
+ }
- return nodeFrom;
- }
+ return boost::none;
+ }
AbstractPass::process(expression, context, decl);
- return SYMBOL_INVALID;
+ return boost::none;
}
void
DFGPass::run()
{
init();
return AbstractPass::run();
}
-void
-DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
-{
- processExpression(expression, context, decl);
-}
-
-
void
DFGPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
- __schemes.emplace(scheme.op, scheme);
+ __signatures.emplace(scheme.op, scheme);
}
}
void DFGPass::finish()
{
man->clasp->addDFAData(move(__context.graph));
-}
\ No newline at end of file
+}
diff --git a/cpp/src/pass/dfgpass.h b/cpp/src/pass/dfgpass.h
index 3d06d8b..8622130 100644
--- a/cpp/src/pass/dfgpass.h
+++ b/cpp/src/pass/dfgpass.h
@@ -1,32 +1,34 @@
// Data Flow Graph determination pass
#ifndef DFGPASS_H
#define DFGPASS_H
#include "abstractpass.h"
#include "clasplayer.h"
+#include <boost/optional.hpp>
namespace xreate {
-class DFGPass: public AbstractPass {
+typedef boost::optional<SymbolPacked> SymbolPackedOptional;
+class DFGPass : public AbstractPass<SymbolPackedOptional> {
public:
- void process(const Expression& expression, PassContext context, const std::string& varDecl="");
- SymbolPacked processExpression(const Expression& expression, PassContext context, const std::string& decl="");
+ SymbolPackedOptional process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
DFGPass(PassManager* manager);
unsigned int hash(const CodeScope* scope);
void init();
void run();
void finish();
private:
struct
{
- DFGraph graph;
+ DFAGraph graph;
} __context;
- std::map<Operator, Expression> __schemes;
+ std::map<Operator, Expression> __signatures; //DFA data for particular operators
+ ClaspLayer* clasp;
};
};
-#endif
\ No newline at end of file
+#endif
diff --git a/cpp/src/pass/functiontagspass.cpp b/cpp/src/pass/functiontagspass.cpp
index 6242d55..6c30b77 100644
--- a/cpp/src/pass/functiontagspass.cpp
+++ b/cpp/src/pass/functiontagspass.cpp
@@ -1,21 +1,10 @@
-/*
+
#include "functiontagspass.h"
-#include <QString>
using namespace std;
using namespace xreate;
-FunctionTagsPass::FunctionTagsPass(AST& root)
- : __root(root)
-{
-}
-
void
-FunctionTagsPass::run(ClaspLayer& clasp)
+FunctionTagsPass::process(ManagedFnPtr function)
{
- for (ManagedFnPtr id=0, count = __root.getFunctionsCount(); id < count; ++id)
- {
- const Function& f = __root.getFunctionById(id);
- clasp.addFunctionTags(f.getName(), f.getAnnotations());
- }
+ man->clasp->addFunctionTags(function->getName(), function->getAnnotations());
}
-*/
\ No newline at end of file
diff --git a/cpp/src/pass/functiontagspass.h b/cpp/src/pass/functiontagspass.h
index 17b4d53..5d92786 100644
--- a/cpp/src/pass/functiontagspass.h
+++ b/cpp/src/pass/functiontagspass.h
@@ -1,18 +1,14 @@
#ifndef FUNCTIONTAGSPASS_H
#define FUNCTIONTAGSPASS_H
-#include "ast.h"
-#include <iostream>
-#include "clasplayer.h"
+#include "abstractpass.h"
namespace xreate {
-class FunctionTagsPass
+class FunctionTagsPass: public AbstractPass<void>
{
public:
- FunctionTagsPass(AST& root);
- void run(ClaspLayer& clasp);
-private:
- const AST& __root;
+ FunctionTagsPass(PassManager *manager): AbstractPass<void>(manager) {}
+ void process(ManagedFnPtr function) override;
};}
#endif // FUNCTIONTAGSPASS_H
diff --git a/cpp/src/pass/logging.cpp b/cpp/src/pass/logging.cpp
new file mode 100644
index 0000000..0daaf05
--- /dev/null
+++ b/cpp/src/pass/logging.cpp
@@ -0,0 +1,106 @@
+/*
+ * logging.cpp
+ *
+ * Created on: Jun 23, 2015
+ * Author: pgess
+ */
+
+#include "logging.h"
+#include "instructions/instr-containers.h"
+#include "utils.h"
+
+using namespace std;
+using namespace llvm;
+namespace xreate {
+
+
+void Logging::init(ClaspLayer* clasp){
+ auto model = clasp->query(Config::get("logging.id"));
+ if(!model) return;
+
+ for (ClaspLayer::ModelIterator rec = model->first; rec!=model->second; ++rec){
+ std::tuple<SymbolPacked> _v =ClaspLayer::parse<SymbolPacked>(rec->second);
+ Symbol v = clasp->unpack(get<0>(_v));
+
+ SymbolAttachments::put<IsLogging>(v, true);
+ }
+}
+
+void
+Logging::process(const Expression& expression, PassContext context, const std::string& varDecl){
+ if (varDecl.size()){
+ Symbol v = context.scope->findSymbol(varDecl);
+ if (SymbolAttachments::get<IsLogging>(v, false)){
+ CompilePass::FunctionUnit* f = compiler->getFunctionUnit(CompilePass::FunctionQuery(string(context.function->getName())));
+ CompilePass::CodeScopeUnit* u = f->getScopeUnit(context.scope);
+
+ CompilePass::Context compilation{f, u, compiler};
+ inject(v, compilation);
+ }
+ }
+
+ return AbstractPass<void>::process(expression, context, varDecl);
+}
+
+void Logging::inject(const Symbol& symbol, const CompilePass::Context& context){
+ llvm::Value* source = context.scope->compileSymbol(symbol);
+ ExpandedType typSource = man->root->expandType(CodeScope::findDefinition(symbol));
+ string format = "";
+ switch (typSource->__value) {
+ case TypePrimitive::Int : case TypePrimitive::Num : case TypePrimitive::I32: case TypePrimitive::I8:
+ format = "%d\n";
+ break;
+
+ case TypePrimitive::String:
+ format = "%s\n";
+ break;
+
+ default:
+ assert(false && "No appropriate type for logging");
+ }
+
+ containers::Instructions compiler(context);
+
+ LLVMLayer* llvm = context.pass->man->llvm;
+ llvm->builder.SetInsertPoint(*source->use_begin());
+ llvm::Value* formatRaw = compiler.compileConstantStringAsPChar(format, "logformat");
+
+ llvm->builder.CreateCall2(refPrintf, formatRaw, source);
+}
+
+void
+Logging::initOutput(){
+ LLVMLayer* llvm = man->llvm;
+ refPrintf = llvm->module->getFunction("printf");
+
+ if (!refPrintf) {
+ PointerType* typPtrI8 = PointerType::get(IntegerType::get(llvm->module->getContext(), 8), 0);
+ std::vector<Type*>argsPrintf{typPtrI8};
+ FunctionType* signaturePrintf = FunctionType::get(
+ /*Result=*/IntegerType::get(llvm->module->getContext(), 32),
+ /*Params=*/argsPrintf,
+ /*isVarArg=*/true);
+
+ refPrintf = llvm::Function::Create(
+ /*Type=*/signaturePrintf,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"printf", llvm->module); // (external, no body)
+
+ refPrintf->setCallingConv(CallingConv::C);
+ }
+}
+
+Logging::Logging(PassManager* manager)
+ : AbstractPass<void>(manager)
+{
+ initOutput();
+ init(man->clasp);
+}
+
+void
+Logging::initDependencies(CompilePass* pass){
+ compiler = pass;
+}
+
+
+} /* namespace xreate */
diff --git a/cpp/src/pass/logging.h b/cpp/src/pass/logging.h
new file mode 100644
index 0000000..4745a06
--- /dev/null
+++ b/cpp/src/pass/logging.h
@@ -0,0 +1,44 @@
+/*
+ * logging.h
+ *
+ * Created on: Jun 23, 2015
+ * Author: pgess
+ */
+
+#ifndef SRC_LOGGING_H_
+#define SRC_LOGGING_H_
+
+#include "ast.h"
+#include <llvm/IR/Value.h>
+#include "pass/compilepass.h"
+#include "pass/abstractpass.h"
+#include "clasplayer.h"
+
+namespace xreate {
+
+class Logging:public AbstractPass<void>, public IQuery {
+public:
+ void inject(const Symbol& symbol, const CompilePass::Context& context);
+ Logging(PassManager* manager);
+
+ virtual void init(ClaspLayer* clasp);
+ void initDependencies(CompilePass* pass);
+ virtual void process(const Expression& expression, PassContext context, const std::string& varDecl="");
+
+private:
+ CompilePass* compiler = nullptr;
+ llvm::Function* refPrintf;
+ void initOutput();
+};
+
+struct IsLogging{};
+
+template<>
+struct AttachmentsDict<IsLogging> {
+ typedef bool Data;
+ static const unsigned int key = 5;
+};
+
+} /* namespace xreate */
+
+#endif /* SRC_LOGGING_H_ */
diff --git a/cpp/src/passmanager.cpp b/cpp/src/passmanager.cpp
index 5693aaf..37c3f28 100644
--- a/cpp/src/passmanager.cpp
+++ b/cpp/src/passmanager.cpp
@@ -1,25 +1,84 @@
#include <pass/abstractpass.h>
#include "query/containers.h"
#include "passmanager.h"
+#include "pass/compilepass.h"
+
+#include "Parser.h"
+#include "pass/dfgpass.h"
+#include "pass/functiontagspass.h"
+#include "pass/logging.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(Scanner& scanner){
+ Parser parser(&scanner);
+ parser.Parse();
+ assert(!parser.errors->count && "Parser errors");
+
+ PassManager* man = new PassManager;
+ AST* ast = new AST(parser.root);
+
+ man->root = ast;
+ man->clasp = new ClaspLayer();
+
+ man->clasp->ast = man->root;
+ man->llvm = new LLVMLayer(man->root);
+ man->registerPass(new DFGPass(man));
+ man->registerPass(new FunctionTagsPass(man));
+
+ return man;
+}
+
+
+
void
-PassManager::registerPass(AbstractPass* pass)
+PassManager::registerPass(AbstractPassBase* pass)
{
__passes.push_back(pass);
}
-void
+void*
PassManager::run()
{
- for (AbstractPass* pass: __passes)
+ for (AbstractPassBase* pass: __passes)
+ {
+ pass->run();
+ pass->finish();
+ }
+
+ clasp->registerdQuery(new containers::Query());
+ clasp->run();
+
+ CompilePass* compiler = new CompilePass(this);
+ compiler->run();
+
+ //Compiler Dependents:
+ Logging* logger = new Logging(this);
+ logger->initDependencies(compiler);
+ logger->run();
+
+ llvm->print();
+ llvm->initJit();
+ return llvm->getFunctionPointer(compiler->getEntryFunction());
+}
+
+void PassManager::runWithoutCompilation(){
+ for (AbstractPassBase* pass: __passes)
{
pass->run();
pass->finish();
}
clasp->registerdQuery(new containers::Query());
+ clasp->run();
}
PassManager::~PassManager(){}
diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h
index 4875ee7..e9d581c 100644
--- a/cpp/src/passmanager.h
+++ b/cpp/src/passmanager.h
@@ -1,27 +1,31 @@
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include "clasplayer.h"
#include "ast.h"
#include <set>
-
+#include "Scanner.h"
namespace xreate {
-class AbstractPass;
+class AbstractPassBase;
+
class PassManager
{
public:
~PassManager();
- void run();
- void registerPass(AbstractPass* pass);
+ void* run();
+ void runWithoutCompilation();
+ void registerPass(AbstractPassBase* pass);
+ static PassManager* prepareForCode(std::string&& code);
+ static PassManager* prepareForCode(Scanner& scanner);
ClaspLayer* clasp;
LLVMLayer* llvm;
AST* root;
private:
//typedef std::multimap<PassFilter, ASTPass*> FILTERS_STORAGE;
//FILTERS_STORAGE __filters;
- std::list<AbstractPass* > __passes;
+ std::list<AbstractPassBase* > __passes;
}; }
-#endif
\ No newline at end of file
+#endif
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index c317bbd..0881b47 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,155 +1,161 @@
//
// Created by pgess on 3/14/15.
//
#include <clasplayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
-const std::string ID_IMPLEMENTATIONS = "impl_fulfill_cluster";
-const std::string ID_CLUSTERS = "var_cluster";
-const std::string ID_PROTOTYPES = "proto_cluster";
-ImplementationData
+
+Implementation
Query::queryImplementation(xreate::Symbol const &s) {
- typedef SymbolAttachments attachs;
- if (attachs::exists<ImplementationData>(s))
+ typedef SymbolAttachments attach;
+ if (attach::exists<Implementation>(s))
{
- return SymbolAttachments::get<ImplementationData>(s);
+ return attach::get<Implementation>(s);
}
- return ImplementationData(s);
+ return Implementation::create(s);
}
void
Query::init(ClaspLayer* clasp)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//read all proto data
- auto range = clasp->query(ID_PROTOTYPES);
- for(ClaspLayer::ModelIterator atom = range.first; atom != range.second; ++atom) {
+ 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->dfgData.unpack(get<0> (data));
- Symbol prototype = clasp->dfgData.unpack(get<1> (data));
+ 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(ID_IMPLEMENTATIONS);
- for(ClaspLayer::ModelIterator atom = range.first; atom != range.second; ++atom)
+ 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->dfgData.unpack(get<0>(data));
+ Symbol var = clasp->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
- ImplementationData impl(var);
- SymbolAttachments::put<ImplementationData>(var, move(impl));
+ Implementation impl = Implementation::create(var);
+ SymbolAttachments::put<Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
- //fill implementation dara for a cluster roots
+ //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);
}
- ImplementationData impl(root.first, root.second, SymbolAttachments::get<ImplementationData>(prototype));
- SymbolAttachments::put<ImplementationData>(root.first, move(impl));
+ SymbolAttachments::put<Implementation>(root.first, Implementation(SymbolAttachments::get<Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
- range = clasp->query(ID_CLUSTERS);
- for(ClaspLayer::ModelIterator atom = range.first; atom != range.second; ++atom)
+ 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->dfgData.unpack(get<0>(info));
- Symbol child = clasp->dfgData.unpack(get<1>(info));
+ Symbol root = clasp->unpack(get<0>(info));
+ Symbol child = clasp->unpack(get<1>(info));
if (!(child == root)) {
- ImplementationData rootImpl = SymbolAttachments::get<ImplementationData>(root);
- SymbolAttachments::put<ImplementationData>(child, move(rootImpl));
+ Implementation rootImpl = SymbolAttachments::get<Implementation>(root);
+ SymbolAttachments::put<Implementation>(child, move(rootImpl));
}
-
}
flagIsDataLoaded = true;
}
-ImplementationData::ImplementationData(Symbol var)
-{
+//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
+Implementation
+Implementation::create(const Symbol &var)
+{
Expression varDecl = CodeScope::findDeclaration(var);
switch (varDecl.op)
{
- case Operator::LIST_RANGE:
- range=var;
- impl = ON_THE_FLY;
- break;
-
- case Operator::LIST:
- impl = LLVM_CONST_ARRAY;
- size = varDecl.getOperands().size();
- break;
-
- default:
- assert(false && "unable to determine proper implementation for the symbol");
- break;
+ 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()}};
+ }
};
+
+ ImplementationLinkedList ill(var);
+ if (ill){
+ return ill.getImplementationData();
+ }
+
+ assert(false && "Unable to determine proper implementation for the symbol");
}
-ImplementationData::ImplementationData(Symbol var, std::string implSerialized, const ImplementationData& implPrototype)
+Implementation
+Implementation::create(const Symbol& var, const std::string& implSerialized)
{
- if (implSerialized == "llvm_array")
+ Expression varDecl = CodeScope::findDeclaration(var);
+ if (implSerialized == Config::get("containers.impl.solid"))
{
- impl = LLVM_ARRAY;
- size = implPrototype.size;
-
- } else if (implSerialized == "llvm_const_array") {
- impl = LLVM_CONST_ARRAY;
- size = implPrototype.size;
+ return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
- } else if (implSerialized == "on_the_fly") {
- impl = ON_THE_FLY;
- range = implPrototype.range;
-
- } else {
- assert(false && "unable to determine proper implementation for the symbol");
+ } 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");
}
-std::pair<xreate::Expression, xreate::Expression>
-ImplementationData::getRange()
-{
- switch (impl) {
- case ON_THE_FLY: {
- Expression decl = CodeScope::findDeclaration(range);
- assert(decl.getOperands().size() == 2);
- return make_pair(decl.getOperands()[0], decl.getOperands()[1]);
- }
+ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
+ : flagIsValid(false), s(source){
- default: {
- return make_pair(Expression(Atom<Number_t>(0)), Expression(Atom<Number_t>(size - 1)));
- }
- };
+ const Expression& sourceExpr = CodeScope::findDeclaration(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 d91a89d..6da2c5e 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,49 +1,80 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "passmanager.h"
+#include <boost/variant.hpp>
namespace xreate {
namespace containers {
- enum Implementation{
- LLVM_ARRAY, LLVM_CONST_ARRAY, ON_THE_FLY
+ 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 ImplementationData {
- Implementation impl;
- union {
- unsigned int size; //valid in case of LLVM_ARRAY impl.
- struct {
- Symbol range;
- };
- };
- ImplementationData(Symbol var);
- ImplementationData(Symbol var, std::string implSerialized, const ImplementationData& implPrototype);
- std::pair<Expression, Expression> getRange();
+ 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 ImplementationData queryImplementation(xreate::Symbol const &s);
+ static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
+
+
}
- template<>
- struct AttachmentsDictionary<containers::ImplementationData> {
- typedef containers::ImplementationData Data;
+ template<>
+ struct AttachmentsDict<containers::Implementation> {
+ typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/query/ptrvalid.cpp b/cpp/src/query/ptrvalid.cpp
new file mode 100644
index 0000000..ff31d76
--- /dev/null
+++ b/cpp/src/query/ptrvalid.cpp
@@ -0,0 +1,15 @@
+/*
+ * QueryPtrValid.cpp
+ *
+ * Created on: Jun 17, 2015
+ * Author: pgess
+ */
+
+#include <query/ptrvalid.h>
+
+using namespace xreate;
+
+bool
+QueryPtrValid::assertValidPtr(const Symbol& s) {
+ return false;
+}
diff --git a/cpp/src/query/ptrvalid.h b/cpp/src/query/ptrvalid.h
new file mode 100644
index 0000000..02794c5
--- /dev/null
+++ b/cpp/src/query/ptrvalid.h
@@ -0,0 +1,24 @@
+/*
+ * QueryPtrValid.h
+ *
+ * Created on: Jun 17, 2015
+ * Author: pgess
+ */
+
+#ifndef SRC_QUERY_PTRVALID_H_
+#define SRC_QUERY_PTRVALID_H_
+
+#include <clasplayer.h>
+
+namespace xreate {
+
+class QueryPtrValid: public xreate::IQuery {
+public:
+ QueryPtrValid();
+ virtual void init(ClaspLayer* clasp);
+
+ static bool assertValidPtr(const Symbol& s);
+};
+
+}
+#endif /* SRC_QUERY_PTRVALID_H_ */
diff --git a/cpp/src/utils.cpp b/cpp/src/utils.cpp
new file mode 100644
index 0000000..693a00e
--- /dev/null
+++ b/cpp/src/utils.cpp
@@ -0,0 +1,9 @@
+#include "utils.h"
+
+using namespace xreate;
+
+Config Config::__self = Config();
+
+Config::Config()
+: __storage{json_file{ "config/default.json" }}
+{}
diff --git a/cpp/src/utils.h b/cpp/src/utils.h
index 3eb314f..532b46d 100644
--- a/cpp/src/utils.h
+++ b/cpp/src/utils.h
@@ -1,65 +1,128 @@
#ifndef UTILS_H
#define UTILS_H
-#include "ast.h"
+#include "jeayeson/jeayeson.hpp"
//TODO mark dirty members
/*
template<class T>
struct DdesctructableClass<T> {
}
*/
/*
template<class OriginalType>
struct TagUpdatable{
TagUpdatable(const OriginalType& source)
: __source(source)
{}
TagUpdatable() = delete;
const OriginalType& __source;
};
struct Updatable;
template <class Tag, class OT>
struct TagsDictionary
{};
template<class OT>
struct TagsDictionary<Updatable, OT>
{
typedef TagUpdatable<OT> TagName;
};
template<class Tag, class OT>
struct awareOf
{
awareOf(OT& dest)
: __dest(dest)
{}
awareOf<Tag, OT>&
operator= (const typename TagsDictionary<Tag, OT>::TagName& source)
{
__dest = source.__source;
}
private:
OT& __dest;
};
template<class Tag<OT>>
const OT&
awareOf(const Tag<OT>& holder)
{
return std::forward<OT>(holder.__source);
}
-*/
+ */
+
+namespace xreate {
+ template<class Tag, class Source>
+ struct AddTag {
+
+ explicit
+ AddTag(const Source &&src)
+ : __src(src) { }
+
+ operator const Source&() const{
+ return __src;
+ }
+
+ const Source& get() const{
+ return __src;
+ }
+
+ const Source*
+ operator->() const {
+ return &__src;
+ }
+
+ private:
+ Source __src;
+ };
+
+ struct Expand_t{};
+ template<class Source>
+ using Expanded = AddTag<Expand_t, Source>;
+
+
+ class Config {
+ private:
+ json_map __storage;
+ static Config __self;
+ Config();
+
+ public:
+ static std::string get(std::string key) {
+ return __self.__storage.get_for_path<json_value>(key).get<std::string>();
+ }
+ };
+}
+
+#define RST "\x1B[0m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KYEL "\x1B[33m"
+#define KBLU "\x1B[34m"
+#define KMAG "\x1B[35m"
+#define KCYN "\x1B[36m"
+#define KWHT "\x1B[37m"
+
+#define FRED(x) KRED << x << RST
+#define FGRN(x) KGRN <<x << RST
+#define FYEL(x) KYEL << x << RST
+#define FBLU(x) KBLU << x << RST
+#define FMAG(x) KMAG x RST
+#define FCYN(x) KCYN x RST
+#define FWHT(x) KWHT x RST
+
+#define BOLD(x) "\x1B[1m" x RST
+#define UNDL(x) "\x1B[4m" x RST
#endif // UTILS_H
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
new file mode 100644
index 0000000..3addb1b
--- /dev/null
+++ b/cpp/tests/ast.cpp
@@ -0,0 +1,27 @@
+/*
+ * ast.cpp
+ *
+ * Created on: Jun 11, 2015
+ * Author: pgess
+ */
+
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "pass/functiontagspass.h"
+#include "Parser.h"
+
+using namespace std;
+using namespace xreate;
+
+TEST(AST, Containers1){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+
+ const AST& ast = parser.root;
+
+ fclose(input);
+}
+
+
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
new file mode 100644
index 0000000..15b4e11
--- /dev/null
+++ b/cpp/tests/containers.cpp
@@ -0,0 +1,58 @@
+/*
+ * containers.cpp
+ *
+ * Created on: Jun 9, 2015
+ * Author: pgess
+ */
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "pass/functiontagspass.h"
+#include "Parser.h"
+#include "query/containers.h"
+
+using namespace std;
+using namespace xreate;
+using namespace containers;
+
+TEST(Containers, DISABLED_DFAData1){
+}
+
+TEST(Containers, ContanierLinkedList1){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+
+ AST& ast = parser.root;
+ CodeScope* body = ast.findFunction("test")->getEntryScope();
+ Symbol symb_chilrenRaw = body->findSymbol("childrenRaw");
+
+ containers::ImplementationLinkedList iLL(symb_chilrenRaw);
+
+ ASSERT_EQ(true, static_cast<bool>(iLL));
+ ASSERT_EQ("next", iLL.fieldPointer);
+
+ Implementation impl = Implementation::create(symb_chilrenRaw);
+ ASSERT_NO_FATAL_FAILURE(impl.extract<ON_THE_FLY>());
+
+ ImplementationRec<ON_THE_FLY> recOnthefly = impl.extract<ON_THE_FLY>();
+ ASSERT_EQ(symb_chilrenRaw, recOnthefly.source);
+}
+
+TEST(Containers, Implementation_LinkedListFull){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(scanner));
+ void* mainPtr = program->run();
+ int (*main)() = (int (*)())(intptr_t)mainPtr;
+
+ int answer = main();
+ ASSERT_EQ(16, answer);
+
+ fclose(input);
+}
+
diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp
new file mode 100644
index 0000000..fe5587e
--- /dev/null
+++ b/cpp/tests/externc.cpp
@@ -0,0 +1,105 @@
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "pass/functiontagspass.h"
+#include "Scanner.h"
+#include "Parser.h"
+#include <iostream>
+#include <llvm/Support/DynamicLibrary.h>
+
+using namespace std;
+
+TEST(InterfaceExternC, testAST){
+ std::string code = " \
+ interface(extern-c){ \
+ xml2 = library:: pkgconfig(\"libxml-2.0\"). \
+ \
+ include { \
+ xml2 = [\"libxml/tree.h\"] \
+ }. \
+ } \
+ ";
+
+ Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
+ Parser parser(&scanner);
+ parser.Parse();
+
+ ASSERT_EQ(1, parser.root.__externdata.size());
+
+ for (const ExternEntry& lib: parser.root.__externdata){
+ ASSERT_EQ("libxml-2.0", lib.package);
+ ASSERT_EQ(1, lib.headers.size());
+ ASSERT_EQ("libxml/tree.h", lib.headers.at(0));
+ }
+}
+
+TEST(InterfaceExternC, testfetchPackageHeaders){
+ ExternEntry entry{"libxml-2.0", {}};
+
+ vector<string> args = ExternLayer::fetchPackageFlags(entry);
+ ASSERT_EQ(1, args.size());
+ ASSERT_EQ("-I/usr/include/libxml2", args.at(0));
+}
+
+TEST(InterfaceExternC, testfetchPackageLibs){
+ ExternEntry entry{"libxml-2.0", {}};
+
+ vector<string> args = ExternLayer::fetchPackageLibs(entry);
+ ASSERT_EQ(1, args.size());
+ ASSERT_EQ("-lxml2", args.at(0));
+}
+
+TEST(InterfaceExternC, testLoadLib){
+ std::string msgErr;
+ if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)){
+ cout << msgErr;
+ ASSERT_EQ("", msgErr);
+ }
+
+ ASSERT_TRUE(true);
+}
+
+TEST(InterfaceExternC, testBSD1){
+ std::string code = " \n\
+ interface(extern-c){ \n\
+ libbsd = library:: pkgconfig(\"libbsd\"). \n\
+ \n\
+ include { \n\
+ libbsd = [\"bsd/stdlib.h\"] \n\
+ }. \n\
+ }\n"
+ "main= function():: int; entry{return arc4random() }";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+
+ void* entryPtr = program->run();
+ int (*entry)() = (int (*)())(intptr_t)entryPtr;
+
+ int answer = 24;
+ answer = entry();
+ cout << answer;
+ ASSERT_NE(24, answer);
+}
+
+TEST(InterfaceExternC, testStructFields1){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+
+ AST& ast = parser.root;
+ CodeScope* body = ast.findFunction("test")->getEntryScope();
+
+ Symbol symbTree = body->findSymbol("tree");
+
+ const TypeAnnotation& tTree = CodeScope::findDefinition(symbTree);
+ const ExpandedType& t2Tree = ast.expandType(tTree);
+ LLVMLayer llvm(&ast);
+ TypeUtils utils(&llvm);
+
+ std::vector<std::string>fields = utils.getStructFields(t2Tree);
+
+ auto field = std::find(fields.begin(), fields.end(), "children");
+ ASSERT_TRUE(field != fields.end());
+}
diff --git a/cpp/tests/safety.cpp b/cpp/tests/safety.cpp
new file mode 100644
index 0000000..2af6879
--- /dev/null
+++ b/cpp/tests/safety.cpp
@@ -0,0 +1,9 @@
+#include "gtest/gtest.h"
+
+/**
+ * Safety checks:
+ * (*) valid ptr (not null)
+ */
+TEST(Safety, validptr1){
+
+}
diff --git a/cpp/tests/testBasic.cpp b/cpp/tests/testBasic.cpp
new file mode 100644
index 0000000..8826b37
--- /dev/null
+++ b/cpp/tests/testBasic.cpp
@@ -0,0 +1,27 @@
+
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "pass/functiontagspass.h"
+#include "Scanner.h"
+#include "Parser.h"
+#include <iostream>
+#include <llvm/Support/DynamicLibrary.h>
+
+using namespace std;
+using namespace xreate;
+
+TEST(EntryFunction, test1){
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(
+ "func1 = function(a:: int):: int {a+8} \
+ func2 = function()::int; entry {12 + func1(4)} \
+ "));
+
+ void* entryPtr = program->run();
+ int (*entry)() = (int (*)())(intptr_t)entryPtr;
+
+ int answer = entry();
+ ASSERT_EQ(24, answer);
+}
+
+
+
diff --git a/cpp/tests/testClangAPI.cpp b/cpp/tests/testClangAPI.cpp
new file mode 100644
index 0000000..d426cf1
--- /dev/null
+++ b/cpp/tests/testClangAPI.cpp
@@ -0,0 +1,191 @@
+//
+// Created by pgess on 4/16/15.
+//
+
+#include "gtest/gtest.h"
+
+#include <llvm/IR/DerivedTypes.h>
+#include "clang/Driver/Options.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "/private/prg/vendors/clang/lib/CodeGen/CodeGenTypes.h"
+#include "/private/prg/vendors/clang/lib/CodeGen/CodeGenModule.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "clang/Basic/TargetInfo.h"
+#include <QString>
+
+
+
+using namespace std;
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::tooling;
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+/*
+class PrintFunctionsConsumer : public ASTConsumer {
+public:
+ bool HandleTopLevelDecl(DeclGroupRef DG) override {
+ for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
+ const Decl *D = *i;
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
+ }
+
+ return true;
+ }
+};
+
+class PFAction : public ASTFrontendAction {
+public:
+ virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
+ return llvm::make_unique<PrintFunctionsConsumer>();
+ }
+};
+*/
+
+class PrinterType : public MatchFinder::MatchCallback {
+public :
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ ASTContext* C = Result.Context;
+ llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
+ if (const TypedefDecl* decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
+ QualType Ty = decl->getUnderlyingType();
+
+ llvm::errs() << "<" << Ty.getAsString() << ">" ;
+
+ CodeGenOptions *CGO = new CodeGenOptions;
+
+ const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
+ CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
+
+ llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
+
+ rawTy->dump();
+ results.push_back(rawTy);
+ }
+ }
+
+ std::vector<llvm::Type*> results;
+};
+
+class PrinterFunction: public MatchFinder::MatchCallback {
+public :
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ if (const FunctionDecl* decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
+ QualType Ty = decl->getType();
+
+ llvm::errs() << "<" << Ty.getAsString() << ">" ;
+ ASTContext* C = Result.Context;
+ llvm::Module* M = new llvm::Module("module1", llvm::getGlobalContext());
+ CodeGenOptions *CGO = new CodeGenOptions;
+
+ const llvm::DataLayout& TD = llvm::DataLayout(C->getTargetInfo().getTargetDescription());
+ CodeGen::CodeGenModule *CGM = new CodeGen::CodeGenModule(*C, *CGO, *M, TD, C->getDiagnostics());
+
+ llvm::Type *rawTy = CGM->getTypes().ConvertType(Ty);
+
+ //const clang::FunctionType* Ty = decl->getType()->getAs<clang::FunctionType>();
+ llvm::FunctionType* rawFuncTy = llvm::dyn_cast<llvm::FunctionType>(rawTy);
+ rawFuncTy->dump();
+ results.push_back(rawFuncTy);
+
+ /*
+ llvm::Function* fDeclaration = llvm::Function::Create(rawFuncTy, llvm::GlobalValue::ExternalLinkage, "xxxx", M);
+ fDeclaration->dump();
+ */
+ }
+ }
+
+ std::vector<llvm::Type*> results;
+};
+
+vector<string> argv = {
+ "-I/usr/include/libxml2"
+ ,"-I/usr/local/include"
+ ,"-I/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0/include"
+ ,"-I/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include"
+ ,"-I/usr/include/x86_64-linux-gnu"
+ ,"-I/usr/include"
+};
+
+TEST(ClangAPI, testExternalType)
+{
+
+ //,, "-I/usr/include/linux"
+// "-cc1", "-emit-pch", "-disable-free", "-disable-llvm-verifier", "-mrelocation-model", "static",
+// "-mthread-model", "posix", "-mdisable-fp-elim", "-fmath-errno", "-masm-verbose",
+// "-mconstructor-aliases", "-munwind-tables", "-fuse-init-array", "-target-cpu", "x86-64", "-target-linker-version", "2.25",
+ //"-dwarf-column-info", "-resource-dir", "/usr/lib/llvm-3.7/bin/../lib/clang/3.7.0",
+ //"clang", "--",
+
+
+ /*
+ int argc= argv.size();
+
+ llvm::cl::OptionCategory cat("aaaa");
+ LLVMInitializeNativeTarget();
+ CommonOptionsParser op(argc, &*(argv.begin()), cat);
+ ClangTool tool(op.getCompilations(), op.getSourcePathList());
+ */
+
+ auto matcherType =
+ typedefDecl(hasName("xmlNodePtr")).bind("typename");
+
+ MatchFinder finder;
+ PrinterType printer;
+ finder.addMatcher(matcherType, &printer);
+
+ std::string code = QString("#include \"%1\"").arg("libxml/tree.h").toStdString();
+ //runToolOnCodeWithArgs(newFrontendActionFactory(&finder).get()->create(), code, argv);
+
+ std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
+ ASTContext & context = ast->getASTContext();
+ finder.matchAST(context);
+
+ string signatureExpected = "%struct._xmlNode.0*";
+ ASSERT_EQ(1, printer.results.size());
+
+ llvm::Type* tyActual = printer.results.at(0);
+ string strActual;
+ llvm::raw_string_ostream ss(strActual);
+ tyActual->print(ss);
+ ASSERT_EQ(signatureExpected, ss.str());
+
+ //int x = tool.run(newFrontendActionFactory(&finder).get());
+}
+
+TEST(ClangAPI, testExternalFunction){
+ auto matcherType = functionDecl(hasName("arc4random")).bind("function");
+
+ MatchFinder finder;
+ PrinterFunction printer;
+ finder.addMatcher(matcherType, &printer);
+
+ std::string code = QString("#include \"%1\"").arg("bsd/stdlib.h").toStdString();
+ std::unique_ptr<ASTUnit> ast = buildASTFromCodeWithArgs(code, argv);
+ ASTContext & context = ast->getASTContext();
+ finder.matchAST(context);
+
+ string signatureExpected = "i32 ()";
+ ASSERT_EQ(1, printer.results.size());
+
+ llvm::Type* tyActual = printer.results.at(0);
+ string strActual;
+ llvm::raw_string_ostream ss(strActual);
+ tyActual->print(ss);
+ ASSERT_EQ(signatureExpected, ss.str());
+}
diff --git a/cpp/tests/testClangAPI.h b/cpp/tests/testClangAPI.h
new file mode 100644
index 0000000..aab7ee5
--- /dev/null
+++ b/cpp/tests/testClangAPI.h
@@ -0,0 +1,9 @@
+//
+// 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/testJson.cpp b/cpp/tests/testJson.cpp
new file mode 100644
index 0000000..18e59cb
--- /dev/null
+++ b/cpp/tests/testJson.cpp
@@ -0,0 +1,9 @@
+#include "utils.h"
+#include "gtest/gtest.h"
+using namespace std;
+using namespace xreate;
+
+TEST(JSON, Test1){
+ string key = Config::get("containers.id.implementations");
+ EXPECT_EQ("impl_fulfill_cluster", key);
+}
diff --git a/cpp/tests/testLibXml2.cpp b/cpp/tests/testLibXml2.cpp
new file mode 100644
index 0000000..ada2404
--- /dev/null
+++ b/cpp/tests/testLibXml2.cpp
@@ -0,0 +1,37 @@
+//
+// Created by pgess on 3/28/15.
+//
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <gtest/gtest.h>
+
+using namespace std;
+
+TEST(libxml2, ReadXML)
+{
+ char* docname = "project/documentation.fodt" ;
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ doc = xmlParseFile(docname);
+ if (doc == NULL ) {
+ fprintf(stderr,"Document not parsed successfully. \n");
+ return;
+ }
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ fprintf(stderr,"empty document\n");
+ xmlFreeDoc(doc);
+ return;
+ }
+
+ cur = cur->xmlChildrenNode;
+ int count =0;
+ while (cur != NULL) {
+ printf("child: %s\n", cur->name);
+
+ cur = cur->next;
+ count ++;
+ }
+
+ ASSERT_EQ(17, count);
+}
diff --git a/cpp/tests/testLogging.cpp b/cpp/tests/testLogging.cpp
new file mode 100644
index 0000000..1d6de19
--- /dev/null
+++ b/cpp/tests/testLogging.cpp
@@ -0,0 +1,87 @@
+/*
+ * testLogging.cpp
+ *
+ * Created on: Jun 23, 2015
+ * Author: pgess
+ */
+
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "llvmlayer.h"
+#include "Parser.h"
+#include "pass/compilepass.h"
+#include "pass/logging.h"
+
+using namespace std;
+using namespace xreate;
+
+TEST(Logging, simpleInjection){
+ PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");
+
+ man->runWithoutCompilation();
+ CompilePass* compilator = new CompilePass(man);
+ compilator->run();
+
+ CompilePass::FunctionUnit* fTest = compilator->getFunctionUnit(CompilePass::FunctionQuery("test"));
+ ASSERT_NE(fTest, nullptr);
+ CompilePass::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
+ CodeScope* scopeTest = scopeUnitTest->scope;
+ Symbol symbX = scopeTest->findSymbol("x");
+ TypeAnnotation typX = scopeTest->findDefinition(symbX);
+
+ llvm::Value* retRaw = scopeUnitTest->compile();
+ llvm::BasicBlock& blockTestRaw = fTest->raw->getEntryBlock();
+
+ LLVMLayer* llvm = man->llvm;
+ //llvm->builder.SetInsertPoint(&blockTestRaw);
+ CompilePass::Context params{fTest, scopeUnitTest, compilator};
+
+ Logging l(man);
+ l.inject(symbX, params);
+
+
+ llvm->initJit();
+ int (*f)() = (int(*)()) llvm->getFunctionPointer(fTest->raw);
+ testing::internal::CaptureStdout();
+ f();
+ std::string&& output = testing::internal::GetCapturedStdout();
+ EXPECT_STREQ("10\n", output.c_str());
+}
+
+TEST(Logging, simpleInjection2){
+ PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int; logging. return x}");
+
+ man->runWithoutCompilation();
+ CompilePass* compiler= new CompilePass(man);
+ compiler->run();
+
+ Logging* logger = new Logging(man);
+ logger->initDependencies(compiler);
+ logger->run();
+
+ man->llvm->initJit();
+ man->llvm->print();
+ int (*f)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction());
+ testing::internal::CaptureStdout();
+ f();
+ std::string&& output = testing::internal::GetCapturedStdout();
+ EXPECT_STREQ("10\n", output.c_str());
+}
+
+TEST(Logging, simpleInjection3){
+ FILE* input = fopen("scripts/cases/log.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(scanner));
+ void* mainPtr = program->run();
+ int (*main)() = (int (*)())(intptr_t)mainPtr;
+
+ int answer = main();
+
+ fclose(input);
+}
+
+
+
+
diff --git a/cpp/tests/tests.cpp b/cpp/tests/tests.cpp
index 81ce6e8..d0e8410 100644
--- a/cpp/tests/tests.cpp
+++ b/cpp/tests/tests.cpp
@@ -1,113 +1,135 @@
-#include "Scanner.h"
-#include "Parser.h"
-#include "ast.h"
-#include <memory>
-#include <iostream>
-#include "clasplayer.h"
-#include "passmanager.h"
-#include "pass/dfgpass.h"
+#include "utils.h"
+#include <gtest/gtest.h>
using namespace std;
+using namespace xreate;
-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);
+int main(int argc, char **argv) {
+ testing::GTEST_FLAG(color) = "yes";
- AST& root = parser->root;
- LLVMLayer l;
-
- 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();
- */
+ 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();
}
-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();
- m.root = & parser->root;
- m.clasp->ast = m.root;
-
- m.registerPass(new DFGPass(&m));
- m.run();
-
- m.clasp->run();
- m.root->compile(*m.llvm);
- m.root->run(*m.llvm);
-}
-
-int main()
-{
- test_DFG_1();
-
- return 0;
-}
+//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/types.cpp b/cpp/tests/types.cpp
new file mode 100644
index 0000000..1f63042
--- /dev/null
+++ b/cpp/tests/types.cpp
@@ -0,0 +1,129 @@
+/*
+ * types.cpp
+ *
+ * Created on: Jun 4, 2015
+ * Author: pgess
+ */
+
+#include "gtest/gtest.h"
+#include "passmanager.h"
+#include "llvmlayer.h"
+#include "Parser.h"
+
+using namespace std;
+using namespace xreate;
+
+TEST(Types, DependantTypes1) {
+ string&& code = "XmlNode = type alias {\n"
+ " tag:: string,\n"
+ " /* attrs:: [string],*/\n"
+ " content:: string\n"
+ "}.\n";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ ExpandedType typeXmlNode = program->root->findType("XmlNode");
+
+ ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator);
+ ASSERT_EQ(2, typeXmlNode->__operands.size());
+ ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
+ ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value);
+}
+
+TEST(Types, DependantTypes2) {
+ string&& code = "XmlNode = type alias {\n"
+ " tag:: string,\n"
+ " /* attrs:: [string],*/\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Template = type Template(Leaf) [Leaf, [Leaf[content]]]."
+ "Concrete = type alias Template(XmlNode).";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
+
+
+ ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
+ ASSERT_EQ(2, typeConcrete->__operands.size());
+ ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
+
+ ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
+ ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
+}
+
+TEST(Types, TreeType1) {
+ string&& code = "XmlNode = type alias {\n"
+ " tag:: string,\n"
+ " /* attrs:: [string],*/\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
+ "Concrete = type alias Tree(XmlNode).";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
+
+ ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator);
+ ASSERT_EQ(2, typeConcrete->__operands.size());
+ ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator);
+
+ ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator);
+
+ auto typeLink = typeConcrete->__operands.at(1).__operands.at(0);
+ ASSERT_EQ(TypeOperator::LINK, typeLink.__operator);
+ ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId);
+}
+
+TEST(Types, TreeType1LLvm){
+ string&& code = "XmlNode = type alias {\n"
+ " tag:: string,\n"
+ " /* attrs:: [string],*/\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]."
+ "Concrete = type alias Tree(XmlNode).";
+
+ std::unique_ptr<PassManager> program(PassManager::prepareForCode(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
+
+ llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
+}
+
+TEST(Types, ArrayOfExternal1){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+
+ AST& ast = parser.root;
+ CodeScope* body = ast.findFunction("test")->getEntryScope();
+
+ Symbol symb = body->findSymbol("childrenRaw");
+
+ const TypeAnnotation& t = CodeScope::findDefinition(symb);
+ const ExpandedType& t2 = ast.expandType(t);
+ EXPECT_EQ(t2->__operator, TypeOperator::ARRAY);
+}
+
+TEST(Types, ExternType1){
+ FILE* input = fopen("scripts/testspass/Containers_Implementation_LinkedList1.xreate","r");
+ assert(input != nullptr);
+
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
+
+ AST& ast = parser.root;
+ CodeScope* body = ast.findFunction("test")->getEntryScope();
+
+ Symbol symbTree = body->findSymbol("tree");
+
+ const TypeAnnotation& t = CodeScope::findDefinition(symbTree);
+ const ExpandedType& t2 = ast.expandType(t);
+ EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
+}
+
diff --git a/scripts/input.xreate b/scripts/cases/containers.xreate
similarity index 57%
copy from scripts/input.xreate
copy to scripts/cases/containers.xreate
index d588ab6..31ecddf 100644
--- a/scripts/input.xreate
+++ b/scripts/cases/containers.xreate
@@ -1,28 +1,36 @@
+/*
+ *
+ * Show-case for a automatic adjustment of container implementations based on actual operations.
+ * Possible implementations: llvm_array, llvm_const_array, on_the_fly(unwinded container)
+ *
+ */
+
pass(dfa) {
- operator map: (op(seqaccess)) -> impl(llvm_array);
+ operator map: (op(seqaccess)) -> impl(solid);
operator list_range: ()->impl(on_the_fly);
- operator list: ()->impl(llvm_const_array);
+ operator list: ()->impl(solid);
operator fold: (op(seqaccess));
operator index: (op(randaccess));
/* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
}
import raw("core/containers.lp");
-testfunc4 = function: ()->bool
+testfunc = function: ()->bool
{
a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : [num];
a2 = [1 .. 100] : [num];
b = loop map (a1 -> el: num) : [num]
- {2 * el;};
+ {2 * el;};
c = b : [num];
d = loop fold (a2->el: num, 0->acc: num): [num]
{acc + el;};
c[5]==d;
}
+
diff --git a/scripts/cases/log.xreate b/scripts/cases/log.xreate
new file mode 100644
index 0000000..1bb0ac9
--- /dev/null
+++ b/scripts/cases/log.xreate
@@ -0,0 +1,64 @@
+/*
+
+ Log level:
+ Log entry(flat, hierarchical)
+
+*/
+
+
+
+
+ // EXTERN INCLUDES
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h", "string.h"]
+ }.
+}
+
+ // CONTAINERS
+interface(dfa) {
+ operator map:: (op(seqaccess)) -> impl(solid).
+ operator list_range:: ()->impl(on_the_fly).
+ operator list:: ()->impl(solid).
+ operator fold:: (op(seqaccess)).
+ operator index:: (op(randaccess)).
+ /* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
+}
+
+import raw("core/containers.lp").
+
+
+ // PROGRAM
+XmlNode = type alias {
+ tag:: string,
+ /* attrs:: [string],*/
+ content:: string
+}.
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+
+test= function():: num; entry {
+ filename = "project/documentation.fodt" :: string.
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+ childrenRaw = tree["children"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+ size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int):: int {
+
+// $log{
+// count +1:: warning, subsystem=xml
+// }
+
+
+ //log{warning, subsystem=xml, ..}
+ childName = child["name"]::string; logging.
+ count + strlen(childName):: int
+ }.
+
+ size
+}
+
+
diff --git a/scripts/containers-set-intersection.xreate b/scripts/containers-set-intersection.xreate
new file mode 100644
index 0000000..22b378d
--- /dev/null
+++ b/scripts/containers-set-intersection.xreate
@@ -0,0 +1,11 @@
+/**
+ * intersection of two sets
+ */
+
+intersection = function(X: [a], sorted; Y: [b], sorted)
+{
+ loop map (X -> x: a | exists(Y, x))
+ {x;};
+}
+
+
\ No newline at end of file
diff --git a/scripts/ftransform.li b/scripts/ftransform.li
deleted file mode 100644
index d75c454..0000000
--- a/scripts/ftransform.li
+++ /dev/null
@@ -1,26 +0,0 @@
-//преобразование параметров функции
-
-function(first-function, vars-list(var(x, i32), var(y, i32)), i32,
- div(add(x, 5), y))
-
---------------------------------------------------------------------------------------------------
-
-type(name(ListNode), struct(
- field(name(caption), type(String)),
- field(name(args), type(collection(ListNode)))
-))
-
-
-
-transform(
- name(f-transform), guard(var(name(X), constraints(caption(simple-function)))),
- body(
- set (args, field(X, args),
-
-
- wrap(extract(args, 0), caption(name)),
-
- wrap
- name(field())
- )
-)
diff --git a/scripts/input.xreate b/scripts/input.xreate
index d588ab6..ccb0330 100644
--- a/scripts/input.xreate
+++ b/scripts/input.xreate
@@ -1,28 +1,92 @@
-pass(dfa) {
- operator map: (op(seqaccess)) -> impl(llvm_array);
- operator list_range: ()->impl(on_the_fly);
- operator list: ()->impl(llvm_const_array);
- operator fold: (op(seqaccess));
- operator index: (op(randaccess));
- /* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
+
+
+/* local scope doc ptr */
+
+
+XmlNode = type alias {
+ tag:: string,
+ /* attrs:: [string],*/
+ content:: string
+}.
+
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h"]
+ }.
+}
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+
+test= function():: num; entry {
+ filename = "project/documentation.fodt" :: string.
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+ childrenRaw = tree["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+ size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int) : int {
+ count +1
+ }.
+
+ size
}
-import raw("core/containers.lp");
+/*
+toXmlNode = function (nodeRaw:: xmlNodePtr):: XmlNode
+{
+ {tag = nodeRaw["name"], content=null}
+}
-testfunc4 = function: ()->bool
+children = function (tree:: xmlNodePtr):: XmlTree
{
- a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : [num];
- a2 = [1 .. 100] : [num];
+ childrenRaw = tree["xmlChildrenNode"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+
+ loop map (childrenRaw->childRaw:: xmlNodePtr):: XmlTree {
+ [toXmlNode(childRaw), children(childRaw)]
+ }
+}
- b = loop map (a1 -> el: num) : [num]
- {2 * el;};
-
- c = b : [num];
-
- d = loop fold (a2->el: num, 0->acc: num): [num]
- {acc + el;};
+
+document = function (filename:: string):: XmlTree
+{
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ nodeRaw= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
- c[5]==d;
+ [toXmlNode(nodeRaw), children(nodeRaw)]:: XmlTree
}
+*/
+
+
+
+/*
+query = function (tree:: XmlTree):: [string, string]
+{
+ children = switch :: context(children)
+ case default
+ { [] }
+
+ case tree[0]:: NeedChildren(childrenFilters); ApplyTransform(transFilters)
+ {
+ loop fold (tree[1]->child:: Tree(Leaf) | childrenFilters, null->accum:: [Tree(Leaf)])
+ :: [Tree(Leaf)]
+ {accum + traverse(child):: cases(transFilters) }
+ }.
+
+ node =
+ case node_tag == "style::style", class = node[attrs, "style::name"], exists(class, ParaKnownClasses)
+ {
+ [class, node[attrs, "style::display-name"]]
+ }
+
+ case default
+ {null}.
+
+ node + children
+}
+*/
+
+
diff --git a/scripts/intersection.li2 b/scripts/intersection.li2
deleted file mode 100644
index 6ce957a..0000000
--- a/scripts/intersection.li2
+++ /dev/null
@@ -1,93 +0,0 @@
-// пример реализации процедуры определения пересечения двух множеств
-//
-//
-// A, B - два множества
-
-
-Iterator (Set set) : (Set set, int pos)
-
-next(Iterator Set i): action of Iterator{
- pos++;
-
- return i;
-}
-
-written El_Type x = Iterator/Set/El_Type i : substitution{
- x = i.pos;
-}
-
-
-A overtake B: action of Iterator {
- elB = current (B); //эта команда может превратиться просто в использование elA из вызывающей функции, используя аннотацию context или bag
-
- repeat-post elA<elB
- elA = next(A);
-
- return elA;
-}
-
-intersect(Set A, B) : function, return Set = {
- A, B : sorted
- Set RESULT-SET;
-
-with Iterator
- repeat
- elA = next(A); // при первом вызове указывает на первый элемент
- elB = next(B);
-
- if (elA > elB)
- elB = B overtake A;
- else
- elA = A overake B;
-
- if (elA == elB)
- put(RESULT-SET, elA);
-
-return RESULT-SET
-}
-
-// repeat - бесконечный повтор?
-// repeat-pre - повтор с предусловием, repeat-post - повтор с постусловием
-
-
-
-
- Работа с Map:
- Пример отображения(view), пример №1:
-
-Map/(KEY, VALUE): type = [(KEY, VALUE)];
-
-Map-T ([KEY], [VALUE]): view, pairs: Map/(KEY, VALUE) = {
- keys = map pairs, pair
- (key, ) = pair;
- key
-
- values = map pairs, pair
- (, value) = pair;
- value
-
- return (keys, values)
-}
-
-//(SELECT key, SELECT value) - возможно ли в функцию передавать названия поля, с кот. ей нужно работать.. ?
-
- Пример №2 (свести к поиску 6):
-
-find6: function = {
-x: [int] = [1, 2, 3, 4, 5, 6, 7]; //эффективная инициализация!
-
-y = map x, el
- 2 * el
-
-return exists(x, 12);
-}
-
-
-/**
- * Построить:
- * сортировка :- необходимо ordered-list(linked-list, tree-list)
- * RA доступ :- желательно hash-list или желательно tree-list
- * последовательный доступ :- желательно ordered-list
- *
- *
-Necessarily and ◇ for Possibly
\ No newline at end of file
diff --git a/scripts/opcode.comments b/scripts/opcode.comments
deleted file mode 100644
index 31c457b..0000000
--- a/scripts/opcode.comments
+++ /dev/null
@@ -1,30 +0,0 @@
-
-/*
-
-ASTLispNode
-
-
-transform(
-
- function(__name, __vars), function(name(__name), vars-list(__vars), body(function.body)
-)
-*/
-
-
-add(y, div(add(x, 5), 15))))
-
-
-opcode(add, LLVMAddInstruction)
-opcode(div, LLVMDivideInstruction)
-
-function(name(first-function),
- vars-list(var(name(x), type(i32)), var(name(y), type(i32))),
- return(type(i32)),
- body(
- div(add(x, 5), y)))
-
-function (name(second-f), vars-list, return(type(i32)), body(
- add(add (10, 20), first-function(11, 80))
-))
-
-main(second-f)
\ No newline at end of file
diff --git a/scripts/opcode.li b/scripts/opcode.li
deleted file mode 100644
index 5f62311..0000000
--- a/scripts/opcode.li
+++ /dev/null
@@ -1,14 +0,0 @@
-opcode(add, LLVMAddInstruction)
-opcode(div, LLVMDivideInstruction)
-
-function(name(first-function),
- vars-list(var(name(x), type(i32)), var(name(y), type(i32))),
- return(type(i32)),
- body(
- div(add(x, 5), y)))
-
-function (name(second-f), vars-list, return(type(i32)), body(
- add(add (10, 20), first-function(80, 11))
-))
-
-main(second-f)
\ No newline at end of file
diff --git a/scripts/testspass/Containers_Implementation_LinkedList1.xreate b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
new file mode 100644
index 0000000..cbc893d
--- /dev/null
+++ b/scripts/testspass/Containers_Implementation_LinkedList1.xreate
@@ -0,0 +1,47 @@
+
+ // EXTERN INCLUDES
+interface(extern-c){
+ xml2 = library:: pkgconfig("libxml-2.0").
+
+ include {
+ xml2 = ["libxml/tree.h"]
+ }.
+}
+
+ // CONTAINERS
+interface(dfa) {
+ operator map:: (op(seqaccess)) -> impl(solid).
+ operator list_range:: ()->impl(on_the_fly).
+ operator list:: ()->impl(solid).
+ operator fold:: (op(seqaccess)).
+ operator index:: (op(randaccess)).
+ /* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */
+}
+
+import raw("core/containers.lp").
+
+
+ // PROGRAM
+XmlNode = type alias {
+ tag:: string,
+ /* attrs:: [string],*/
+ content:: string
+}.
+
+Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]].
+XmlTree = type alias Tree(XmlNode).
+
+
+test= function():: num; entry {
+ filename = "project/documentation.fodt" :: string.
+ docRaw = xmlParseFile(filename) :: xmlDocPtr.
+ tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr.
+ childrenRaw = tree["children"]:: [xmlNodePtr]; containers:linkedlist(next, null).
+ size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count::int):: int {
+ count +1::int
+ }.
+
+ size
+}
+
+
diff --git a/scripts/xml/xml-backup.xreate b/scripts/xml/xml-backup.xreate
new file mode 100644
index 0000000..7fe9246
--- /dev/null
+++ b/scripts/xml/xml-backup.xreate
@@ -0,0 +1,65 @@
+default_filname = "project/documentation.fodt" : string;
+
+/* require ptrvalid */
+/* local scope doc ptr */
+
+XmlNode = type {
+ tag: string;
+ attrs: [string];
+ content: string}.
+
+Tree = type(Leaf) Tree [Leaf; [Tree(Leaf)]];
+
+XmlTree = Tree(XmlNode);
+
+
+children = function: (tree: xmlNodePtr)->XmlTree
+{
+ childrenRaw = tree[xmlChildrenNode]: [xmlNodePtr], linkedlist(next, null);
+
+ map (childrenRaw->childRaw: xmlNodePtr) {
+ Tree[childRaw[name] children(childRaw)]
+ }
+}
+
+
+document = function: (filename: string)->XmlTree
+{
+ docRaw = xmlParseFile(docname.c_str()) : xmlDocPtr;
+ nodeRaw= xmlDocGetRootElement(docRaw) : xmlNodePtr;
+
+ Tree [nodeRaw[name] children(nodeRaw));
+}
+
+
+query = function: (tree: XmlTree) [string, string]
+{
+ children : context(children) =
+ case default
+ []
+
+ case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
+ {
+ loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
+ {accum + traverse(child): cases(transFilters) };
+ }
+
+ node =
+ case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
+ {
+ [class, node[attrs, "style:display-name"]];
+ }
+
+ case default
+ [] ;
+
+ node + children;
+}
+
+
+test = function: ()->num
+{
+ data = query(document(default_filename)): [string, string];
+
+ exists(data, "pgess1").
+}
diff --git a/scripts/xml/xml-client.xreate b/scripts/xml/xml-client.xreate
new file mode 100644
index 0000000..dc1b2cb
--- /dev/null
+++ b/scripts/xml/xml-client.xreate
@@ -0,0 +1,71 @@
+/*
+
+Example of c++ code:
+
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ doc = xmlParseFile(docname.c_str());
+ if (doc == NULL ) {
+ fprintf(stderr,"Document not parsed successfully. \n");
+ return;
+ }
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ fprintf(stderr,"empty document\n");
+ xmlFreeDoc(doc);
+ return;
+ }
+
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ printf("child: %s\n", cur->name);
+
+ cur = cur->next;
+ }
+
+*/
+
+/*
+
+ Default strategies:
+ - what to do with unspecified nodes
+
+ Node content strategy:
+ - send as-is
+ - apply transforms (all / named)
+ - ?? skip
+
+ Processing order:
+ - dependencies
+
+ */
+
+query = function(tree: XmlTree): [XmlTree]
+{
+ children : context(children) =
+ case default
+ []
+
+ case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
+ {
+ loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
+ {accum + traverse(child): cases(transFilters) };
+ }
+
+ node =
+ case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
+ {
+ [class, node[attrs, "style:display-name"]];
+ }
+
+ case default
+ [] ;
+
+ Tree[node children] | node + children
+}
+
+ /*
+traverse = function(trees: [XmlTree]) : [XmlTree]
+ loop fold(trees->tree: Tree; []->acc)
+ acc + traverse(tree)
+ */
\ No newline at end of file
diff --git a/scripts/xml/xml-query.xreate b/scripts/xml/xml-query.xreate
new file mode 100644
index 0000000..60a330e
--- /dev/null
+++ b/scripts/xml/xml-query.xreate
@@ -0,0 +1,38 @@
+XmlNode = type {
+ tag: string;
+ attrs: [string];
+ content: string}.
+
+Tree = type(Leaf) Tree [Leaf; [Tree(Leaf)]].
+
+XmlTree = Tree(XmlNode).
+
+query = function(tree: XmlTree): [XmlTree]
+{
+ children : context(children) =
+ case default
+ []
+
+ case (tree[0]: NeedChildren(childrenFilters), ApplyTransform(transFilters))
+ {
+ loop fold (tree[1]->child: Tree(Leaf) | childrenFilters; []->accum).
+ {accum + traverse(child): cases(transFilters) };
+ }
+
+ node =
+ case (node.tag == "style:style"; class = node[attrs, "style:name"]; exists(class, ParaKnownClasses))
+ {
+ [class, node[attrs, "style:display-name"]];
+ }
+
+ case default
+ [] ;
+
+ Tree[node children] | node + children
+}
+
+ /*
+traverse = function(trees: [XmlTree]) : [XmlTree]
+ loop fold(trees->tree: Tree; []->acc)
+ acc + traverse(tree)
+ */
\ No newline at end of file
diff --git a/src/main/java/org/xreate/ASTNode.java b/src/main/java/org/xreate/ASTNode.java
deleted file mode 100644
index 02b1e07..0000000
--- a/src/main/java/org/xreate/ASTNode.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-
-public class ASTNode{
- public ASTNode acceptComputableVisitor(ComputableAnalysis visitor) throws NoSuchMethodException, IllegalAccessException, Throwable{
- Method compute = visitor.getClass().getDeclaredMethod("ifComputable", this.getClass());
-
- ASTNode v = (ASTNode) compute.invoke(visitor, this);
-
- return new ASTValue(0);
- }
-}
-
-class ASTAssignment extends ASTNode{
- public ASTVar var;
- public ASTExpression value;
-}
-
-class ASTExpression extends ASTNode{
- ListMultimap <ASTFunction, ASTExpression> representation;
-
- public List<ASTVar> getUsedVars(){
- return Lists.newArrayList(); //stub
- }
-
-
- public ASTNode eval(Map<ASTVar, ASTNode> substitutions)
- {return new ASTValue(0);} //stub
-
-}
-
-class ASTFunction extends ASTNode{
- String representation;
- int fpcount; //formal parameters count
-}
-
-
-class ASTValue extends ASTExpression{
- public int representation;
-
- public ASTValue(int source){
- representation = source;
- }
-}
-
-class ASTVar extends ASTExpression{
- int id;
-
- public static Map<ASTVar, ASTValue> substitute(List<ASTVar> vars)
- {return Maps.newHashMap();}
-
- public ASTVar(){
- id =0;
- }
-}
-
-
-
-
-/*
- * fargs - formal args
- *
- *
- *
- */
-
-/*
- *
- *
- * block (fargs, body-list)
- * expression -: atom
- * atom :- val, var
- * assignment
- * sequence
- *
- */
-
diff --git a/src/main/java/org/xreate/App.java b/src/main/java/org/xreate/App.java
deleted file mode 100644
index ba10572..0000000
--- a/src/main/java/org/xreate/App.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.xreate;
-
-public class App
-{
- public static void main( String[] args ) throws NoSuchMethodException, IllegalAccessException, Throwable {
- TestRunner2 runner = new TestRunner2();
-
- runner.constructAndRun();
- }
-}
diff --git a/src/main/java/org/xreate/ComputableAnalisys.java b/src/main/java/org/xreate/ComputableAnalisys.java
deleted file mode 100644
index d64a7cc..0000000
--- a/src/main/java/org/xreate/ComputableAnalisys.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- * @author pgess
- */
-class ComputableAnalysis{
- protected Map<ASTVar, ASTNode> computedStore;
-
- public ASTNode ifComputable (ASTNode node){
- return node;
- }
-
- /*
- * null - если не переменная не вычислима
- */
- public ASTNode ifComputable (ASTVar node){
-
- return computedStore.get(node);
-
- /*
- Optional<ASTValue> value = Optional.of ();
- return false;
- */
- }
-
- /*
- * null - если выражение не вычислимо
- */
- /*
- public ASTNode ifComputable (ASTExpression node){
- List<ASTVar> vars = node.getUsedVars();
-
- Map<ASTVar, ASTValue> subs = ASTVar.substitute(vars);
-
- if (computedStore.keySet().containsAll(vars)){
-
- //computedStore.
- ASTNode result = node.eval(subs);
- return result;
- }
-
-
- return null;
- }
-
- */
-
- public ASTNode ifComputable (ASTAssignment node) throws NoSuchMethodException, IllegalAccessException, Throwable{
-
- ASTNode value = node.value.acceptComputableVisitor(this);
-
- if (value != null){
- computedStore.put(node.var, value);
- }
-
- return value;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/xreate/SemanticAnalysis.java b/src/main/java/org/xreate/SemanticAnalysis.java
deleted file mode 100644
index a411db6..0000000
--- a/src/main/java/org/xreate/SemanticAnalysis.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate;
-
-import java.util.Map;
-
-/**
- *
- * @author pgess
- */
-public class SemanticAnalysis {
- public Map<String, String> opcodes;
-}
diff --git a/src/main/java/org/xreate/TestRunner2.java b/src/main/java/org/xreate/TestRunner2.java
deleted file mode 100644
index 5c519c4..0000000
--- a/src/main/java/org/xreate/TestRunner2.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate;
-
-import com.google.common.collect.Maps;
-import java.math.BigInteger;
-import org.jllvm.*;
-import org.jllvm.bindings.*;
-import org.junit.Test;
-/**
- *
- * @author pgess
- */
-public class TestRunner2 {
-
- protected LLVMModule module;
-
- public void setModule(LLVMModule module){
- this.module = module;
- }
-
- public void constructAndRun() throws Exception{
- boolean isNative = LLVMTargetData.initializeNativeTarget();
- module = new LLVMModule("xreate_first_test");
-
- LLVMValue func = constructBody();
- runBody(func);
- }
-
- public LLVMValue constructBody() throws Exception{
- LLVMConstantInteger a = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 10, true);
- LLVMConstantInteger b = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 20, true);
- LLVMConstantInteger c = LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, 3, true);
- LLVMInstructionBuilder builder = new LLVMInstructionBuilder();
-
- LLVMInstruction i = new LLVMAddInstruction(builder, a, b, false, "a+b");
- i = new LLVMMultiplyInstruction(builder, c, i, false, "c * (a + b)");
-
- //LLVMModule module; // module =
- LLVMFunctionType func_test1_type;
-
-
-
- LLVMType[] types = new LLVMType[0];
- //types[0] = new LLVMVoidType();
-
- func_test1_type = new LLVMFunctionType(LLVMIntegerType.i32, types, false);
-
- LLVMFunction test1 = new LLVMFunction(module, "test1", func_test1_type);
- LLVMBasicBlock entry = test1.appendBasicBlock("entry");
- builder.positionBuilderAtEnd(entry);
-
- new LLVMReturnInstruction(builder, i);
-
- SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
- int x = Analysis.LLVMVerifyFunction(test1.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction);
- x = Analysis.LLVMVerifyModule(module.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction, outerrs);
-
- ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
-
- return test1;
- }
-
- public void runBody(LLVMValue test1 ){
-
-
- SWIGTYPE_p_p_LLVMOpaqueExecutionEngine engines = ExecutionEngine.new_LLVMExecutionEngineRefArray(1);
- SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
- int success = ExecutionEngine.LLVMCreateJITCompilerForModule(engines,module.getInstance(), 0, outerrs);
- String outerr = ExecutionEngine.StringArray_getitem(outerrs,0);
- ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
- SWIGTYPE_p_LLVMOpaqueExecutionEngine instance_ = ExecutionEngine.LLVMExecutionEngineRefArray_getitem(engines,0);
- ExecutionEngine.delete_LLVMExecutionEngineRefArray(engines); engines = null;
-
- /*
- LLVMJitCompiler engine = new LLVMJitCompiler(module);
-
- LLVMGenericValue res = engine.runFunction(test1, args);
-
- //
- BigInteger result = ExecutionEngine.LLVMGenericValueToInt(res.getInstance(), 0);
- */
-
- LLVMGenericValue[] args = new LLVMGenericValue[0];
-
-
- SWIGTYPE_p_p_LLVMOpaqueGenericValue arg_array = ExecutionEngine.new_LLVMGenericValueRefArray(args.length);
- for(int ii=0;ii<args.length;ii++)
- ExecutionEngine.LLVMGenericValueRefArray_setitem(arg_array,ii,args[ii].getInstance());
-
- SWIGTYPE_p_LLVMOpaqueGenericValue res = ExecutionEngine.LLVMRunFunction(instance_,test1.getInstance(),args.length,arg_array);
- ExecutionEngine.delete_LLVMGenericValueRefArray(arg_array);
-
- BigInteger result = ExecutionEngine.LLVMGenericValueToInt(res, 0);
- //LLVMGenericInt result = (LLVMGenericInt) new LLVMGenericValue(res);
-
-
- /*
- LLVMJitCompiler program = new LLVMJitCompiler (module);
- LLVMGenericInt result = (LLVMGenericInt) program.runFunction(test1, new LLVMGenericValue[0]);
- */
-
-
- int r = result.intValue();
-
- System.out.println(r);
- }
-
- static {
- System.loadLibrary("jllvm");
- }
-}
diff --git a/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java b/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java
deleted file mode 100644
index 561443f..0000000
--- a/src/main/java/org/xreate/grammatic/lisp/ASTLispNode.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate.grammatic.lisp;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.util.ArrayList;
-import java.util.Map;
-
-
-public class ASTLispNode {
- public String caption;
- public ArrayList<ASTLispNode> parameters = Lists.newArrayList();
-
- protected Map<String, ASTLispNode> index;
-
- public ASTLispNode(String c){
- caption = c;
- }
-
- public ASTLispNode add(ASTLispNode node){
- parameters.add(node);
- return node;
- }
-
- public ASTLispNode get(String node){
- if (null == index){
- buildIndex();
- }
-
- return index.get(node);
- }
-
- protected void buildIndex(){
- index = Maps.newHashMap();
-
- for (ASTLispNode param : parameters){
- index.put(param.caption, param);
- }
- }
-}
-class ASTLispConstantNode extends ASTLispNode{
- public int value;
-
- public ASTLispConstantNode(String c) {
- super(c);
-
- value = Integer.parseInt(c);
- }
-}
-
-
-class NodeFunctionVarsList {
- ASTLispNode node;
-
- NodeFunctionVarsList(ASTLispNode node){
- this.node = node;
- }
-
- String[] getVarNames(){
- int size = node.parameters.size();
-
- String[] result = new String[size];
-
- for(int i=0; i<size; i++){
- result[i] = node.parameters.get(i).get("name").parameters.get(0).caption;
- }
-
- return result;
- }
-}
diff --git a/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java b/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java
deleted file mode 100644
index 56a77d3..0000000
--- a/src/main/java/org/xreate/grammatic/lisp/LispInterpreter.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate.grammatic.lisp;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import org.antlr.runtime.*;
-import org.jllvm.*;
-import org.jllvm.bindings.*;
-import org.xreate.TestRunner2;
-
-/**
- *
- * @author pgess
- */
-public class LispInterpreter {
- static Map<String, String> htable;
- static Map<String, LLVMType> ttable;
-
- public Map<String, String> opcodes = Maps.newLinkedHashMap();
- public Map<String, LLVMFunction> functions = Maps.newLinkedHashMap();
-
-
- protected LLVMInstructionBuilder builder = new LLVMInstructionBuilder();
- protected LLVMModule module = new LLVMModule("script");
-
- //"/private/prg/code/xreate/scripts/opcode.li"
- public void run(String filename) throws IOException, RecognitionException, Exception{
- ANTLRStringStream in = new ANTLRFileStream(filename);
-
- Lexer l = new LispLexer(in);
- CommonTokenStream tokens = new CommonTokenStream(l);
-
- LispParser p = new LispParser(tokens);
-
- while (true){
- ASTLispNode node = p.statement(null);
-
- handle(node);
- }
-
- }
-
- public void opcodeDef(ASTLispNode node){
- ArrayList<ASTLispNode> params = node.parameters;
-
- opcodes.put(params.get(0).caption, params.get(1).caption);
- }
-
- public void functionDef(ASTLispNode node) throws Exception{
- ArrayList<ASTLispNode> nodes_vars = node.get("vars-list").parameters;
-
- int nsize = nodes_vars.size();
- LLVMType[] arg_types = new LLVMType[nsize];
-
- for (int i=0; i<nsize; i++){
- String type_caption = nodes_vars.get(i).get("type").parameters.get(0).caption;
- arg_types[i] = ttable.get(type_caption);
- }
-
- LLVMType ret_type = ttable.get(node.get("return").get("type").parameters.get(0).caption);
- String func_name = node.get("name").parameters.get(0).caption;
-
- LLVMFunctionType func_type =new LLVMFunctionType(ret_type, arg_types, false);
- LLVMFunction func = new LLVMFunction(module, func_name, func_type);
-
- LLVMBasicBlock entry = func.appendBasicBlock("entry");
- builder.positionBuilderAtEnd(entry);
-
- LLVMValue[] values = func.getParameters();
- String[] vars = new NodeFunctionVarsList(node.get("vars-list")).getVarNames();
-
- LLVMValue func_body = new Evaluator(vars, values).eval(node.get("body").parameters.get(0));
-
- new LLVMReturnInstruction(builder, func_body);
-
- SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
- int x = Analysis.LLVMVerifyFunction(func.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction);
- x = Analysis.LLVMVerifyModule(module.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction, outerrs);
- ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
-
- functions.put(func_name, func);
- }
-
- public int main(ASTLispNode node) throws Exception{
-
- String func_main_name = node.parameters.get(0).caption;
- LLVMFunction func_main = functions.get(func_main_name);
- if (null == func_main){
- throw new Exception("Main function not found!");
- }
-
- boolean isNative = LLVMTargetData.initializeNativeTarget();
- LispJITRunnerWrapper program = new LispJITRunnerWrapper(module);
- LLVMGenericValue resultRef = program.runFunction(func_main, new LLVMGenericValue[0]);
- BigInteger resultBig = ExecutionEngine.LLVMGenericValueToInt(resultRef.getInstance(), 0);
- int result = resultBig.intValue();
- return result;
-
- /*
- TestRunner2 runner = new TestRunner2();
- runner.setModule(module);
- runner.runBody(func_main);
-
- return 0;
- *
- */
- }
-
-
-
-
- public Object handle(ASTLispNode node) throws Exception{
- String caption = node.caption;
- String method = htable.get(caption);
-
- if (method == null) {
- throw new Exception();
- }
-
- Method invoker = this.getClass().getDeclaredMethod(method, ASTLispNode.class);
- return invoker.invoke(this, node);
- }
-
- public LispInterpreter(){
- }
-
- static {
- /*
- * Handler table хранит информацию о соответствии метода и команды
- */
- htable = new ImmutableMap.Builder<String, String>()
- .put("opcode", "opcodeDef")
- .put("function", "functionDef")
- .put ("calculate", "calculate")
- .put("main", "main")
- .build();
-
- /*
- * Types Table - хранит информацию о соответствии типов
- */
- ttable = new ImmutableMap.Builder<String, LLVMType>()
- .put ("i32", LLVMIntegerType.i32)
- .put ("i16", LLVMIntegerType.i16)
- .put ("i8", LLVMIntegerType.i8)
- .build();
-
-
- }
-
- class Evaluator{
- Map<String, LLVMValue> arguments;
-
- public Evaluator(String[] names, LLVMValue[] values) {
-
- int size = names.length;
- arguments = Maps.newHashMapWithExpectedSize(size);
-
- for(int i=0; i<size; i++){
- arguments.put(names[i], values[i]);
- }
- }
-
- public LLVMValue LLVMAddInstruction(ASTLispNode node) throws Exception{
-
- LLVMValue arg1 = eval(node.parameters.get(0));
- LLVMValue arg2 = eval(node.parameters.get(1));
-
- return new LLVMAddInstruction(builder, arg1, arg2, false, "add");
- }
-
- public LLVMValue LLVMDivideInstruction(ASTLispNode node) throws Exception{
- LLVMValue arg1 = eval(node.parameters.get(0));
- LLVMValue arg2 = eval(node.parameters.get(1));
-
- return new LLVMDivideInstruction(builder, arg1, arg2, LLVMDivideInstruction.DivisionType.UNSIGNEDINT, "div");
- }
-
- public LLVMValue LLVMCallFunctionInstruction(ASTLispNode node) throws Exception{
- LLVMFunction func = functions.get(node.caption);
-
- int size = node.parameters.size();
-
- LLVMValue[] args = new LLVMValue[size];
-
- for (int i=0; i<size; i++){
- args[i] = eval(node.parameters.get(i));
- }
-
-// long argsNum = Core.LLVMCountParamTypes(Core.LLVMTypeOf(func.getInstance()));
-
- SWIGTYPE_p_p_LLVMOpaqueValue args_opaque = Core.new_LLVMValueRefArray(args.length);
- for(int i=0;i<args.length;i++)
- Core.LLVMValueRefArray_setitem(args_opaque,i,args[i].getInstance());
- SWIGTYPE_p_LLVMOpaqueValue instance = Core.LLVMBuildCall(builder.getInstance(),func.getInstance(),args_opaque,args.length, node.caption + "aaa");
-
- Core.delete_LLVMValueRefArray(args_opaque);
-
- return new LLVMValue(instance);
- //return new LLVMCallInstruction(builder, func, args, node.caption);
- }
-
- public LLVMValue eval(ASTLispNode node) throws Exception{
- if (node instanceof ASTLispConstantNode){
- return LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, ((ASTLispConstantNode) node).value, false);
- }
-
- String instruction = opcodes.get(node.caption);
-
- if (instruction != null) {
- Method invoker = this.getClass().getDeclaredMethod(instruction, ASTLispNode.class);
- return (LLVMValue) invoker.invoke(this, node);
- }
-
- LLVMValue arg = arguments.get(node.caption);
-
- if (arg != null){
- return arg;
- }
-
- if (functions.containsKey(node.caption)){
- return LLVMCallFunctionInstruction(node);
- }
-
- throw new Exception("Cant evaluate symbol: " + node.caption);
- }
-
- }
-}
-
-
-
-class LispJITRunnerWrapper extends LLVMExecutionEngine{
- LispJITRunnerWrapper(LLVMModule module) throws Exception{
- super();
-
- SWIGTYPE_p_p_LLVMOpaqueExecutionEngine engines = ExecutionEngine.new_LLVMExecutionEngineRefArray(1);
- SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
- int success = ExecutionEngine.LLVMCreateJITCompilerForModule(engines,module.getInstance(), 0, outerrs);
- String outerr = ExecutionEngine.StringArray_getitem(outerrs,0);
- ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
- instance = ExecutionEngine.LLVMExecutionEngineRefArray_getitem(engines,0);
- ExecutionEngine.delete_LLVMExecutionEngineRefArray(engines); engines = null;
-
- /*
- if(success == 0)
- throw new Exception(outerr);
- *
- */
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/xreate/grammatic/lisp/LispLexer.java b/src/main/java/org/xreate/grammatic/lisp/LispLexer.java
deleted file mode 100644
index 8f8d69a..0000000
--- a/src/main/java/org/xreate/grammatic/lisp/LispLexer.java
+++ /dev/null
@@ -1,368 +0,0 @@
-package org.xreate.grammatic.lisp;
-
-// $ANTLR 3.4 /private/prg/code/xreate/antlr/lisp.g 2012-04-07 17:57:03
-
-import org.antlr.runtime.*;
-import java.util.Stack;
-import java.util.List;
-import java.util.ArrayList;
-
-@SuppressWarnings({"all", "warnings", "unchecked"})
-public class LispLexer extends Lexer {
- public static final int EOF=-1;
- public static final int T__6=6;
- public static final int T__7=7;
- public static final int T__8=8;
- public static final int WHITESPACE=4;
- public static final int WORD=5;
-
- // delegates
- // delegators
- public Lexer[] getDelegates() {
- return new Lexer[] {};
- }
-
- public LispLexer() {}
- public LispLexer(CharStream input) {
- this(input, new RecognizerSharedState());
- }
- public LispLexer(CharStream input, RecognizerSharedState state) {
- super(input,state);
- }
- public String getGrammarFileName() { return "/private/prg/code/xreate/antlr/lisp.g"; }
-
- // $ANTLR start "T__6"
- public final void mT__6() throws RecognitionException {
- try {
- int _type = T__6;
- int _channel = DEFAULT_TOKEN_CHANNEL;
- // /private/prg/code/xreate/antlr/lisp.g:2:6: ( '(' )
- // /private/prg/code/xreate/antlr/lisp.g:2:8: '('
- {
- match('(');
-
- }
-
- state.type = _type;
- state.channel = _channel;
- }
- finally {
- // do for sure before leaving
- }
- }
- // $ANTLR end "T__6"
-
- // $ANTLR start "T__7"
- public final void mT__7() throws RecognitionException {
- try {
- int _type = T__7;
- int _channel = DEFAULT_TOKEN_CHANNEL;
- // /private/prg/code/xreate/antlr/lisp.g:3:6: ( ')' )
- // /private/prg/code/xreate/antlr/lisp.g:3:8: ')'
- {
- match(')');
-
- }
-
- state.type = _type;
- state.channel = _channel;
- }
- finally {
- // do for sure before leaving
- }
- }
- // $ANTLR end "T__7"
-
- // $ANTLR start "T__8"
- public final void mT__8() throws RecognitionException {
- try {
- int _type = T__8;
- int _channel = DEFAULT_TOKEN_CHANNEL;
- // /private/prg/code/xreate/antlr/lisp.g:4:6: ( ',' )
- // /private/prg/code/xreate/antlr/lisp.g:4:8: ','
- {
- match(',');
-
- }
-
- state.type = _type;
- state.channel = _channel;
- }
- finally {
- // do for sure before leaving
- }
- }
- // $ANTLR end "T__8"
-
- // $ANTLR start "WHITESPACE"
- public final void mWHITESPACE() throws RecognitionException {
- try {
- int _type = WHITESPACE;
- int _channel = DEFAULT_TOKEN_CHANNEL;
- // /private/prg/code/xreate/antlr/lisp.g:3:12: ( ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+ )
- // /private/prg/code/xreate/antlr/lisp.g:3:14: ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+
- {
- // /private/prg/code/xreate/antlr/lisp.g:3:14: ( '\\t' | ' ' | '\\r' | '\\n' | '\\u000C' )+
- int cnt1=0;
- loop1:
- do {
- int alt1=2;
- int LA1_0 = input.LA(1);
-
- if ( ((LA1_0 >= '\t' && LA1_0 <= '\n')||(LA1_0 >= '\f' && LA1_0 <= '\r')||LA1_0==' ') ) {
- alt1=1;
- }
-
-
- switch (alt1) {
- case 1 :
- // /private/prg/code/xreate/antlr/lisp.g:
- {
- if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||(input.LA(1) >= '\f' && input.LA(1) <= '\r')||input.LA(1)==' ' ) {
- input.consume();
- }
- else {
- MismatchedSetException mse = new MismatchedSetException(null,input);
- recover(mse);
- throw mse;
- }
-
-
- }
- break;
-
- default :
- if ( cnt1 >= 1 ) break loop1;
- EarlyExitException eee =
- new EarlyExitException(1, input);
- throw eee;
- }
- cnt1++;
- } while (true);
-
-
- _channel = HIDDEN;
-
- }
-
- state.type = _type;
- state.channel = _channel;
- }
- finally {
- // do for sure before leaving
- }
- }
- // $ANTLR end "WHITESPACE"
-
- // $ANTLR start "WORD"
- public final void mWORD() throws RecognitionException {
- try {
- int _type = WORD;
- int _channel = DEFAULT_TOKEN_CHANNEL;
- // /private/prg/code/xreate/antlr/lisp.g:5:6: ( ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+ )
- // /private/prg/code/xreate/antlr/lisp.g:5:8: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+
- {
- // /private/prg/code/xreate/antlr/lisp.g:5:8: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )+
- int cnt2=0;
- loop2:
- do {
- int alt2=2;
- int LA2_0 = input.LA(1);
-
- if ( ((LA2_0 >= '0' && LA2_0 <= '9')||(LA2_0 >= 'A' && LA2_0 <= 'Z')||LA2_0=='_'||input.LA(1)=='-'||(LA2_0 >= 'a' && LA2_0 <= 'z')) ) {
- alt2=1;
- }
-
-
- switch (alt2) {
- case 1 :
- // /private/prg/code/xreate/antlr/lisp.g:
- {
- if ( (input.LA(1) >= '0' && input.LA(1) <= '9')||(input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_' ||input.LA(1)=='-' ||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) {
- input.consume();
- }
- else {
- MismatchedSetException mse = new MismatchedSetException(null,input);
- recover(mse);
- throw mse;
- }
-
-
- }
- break;
-
- default :
- if ( cnt2 >= 1 ) break loop2;
- EarlyExitException eee =
- new EarlyExitException(2, input);
- throw eee;
- }
- cnt2++;
- } while (true);
-
-
- }
-
- state.type = _type;
- state.channel = _channel;
- }
- finally {
- // do for sure before leaving
- }
- }
- // $ANTLR end "WORD"
-
- public void mTokens() throws RecognitionException {
- // /private/prg/code/xreate/antlr/lisp.g:1:8: ( T__6 | T__7 | T__8 | WHITESPACE | WORD )
- int alt3=5;
- switch ( input.LA(1) ) {
- case '(':
- {
- alt3=1;
- }
- break;
- case ')':
- {
- alt3=2;
- }
- break;
- case ',':
- {
- alt3=3;
- }
- break;
- case '\t':
- case '\n':
- case '\f':
- case '\r':
- case ' ':
- {
- alt3=4;
- }
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case '-':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- {
- alt3=5;
- }
- break;
- default:
- NoViableAltException nvae =
- new NoViableAltException("", 3, 0, input);
-
- throw nvae;
-
- }
-
- switch (alt3) {
- case 1 :
- // /private/prg/code/xreate/antlr/lisp.g:1:10: T__6
- {
- mT__6();
-
-
- }
- break;
- case 2 :
- // /private/prg/code/xreate/antlr/lisp.g:1:15: T__7
- {
- mT__7();
-
-
- }
- break;
- case 3 :
- // /private/prg/code/xreate/antlr/lisp.g:1:20: T__8
- {
- mT__8();
-
-
- }
- break;
- case 4 :
- // /private/prg/code/xreate/antlr/lisp.g:1:25: WHITESPACE
- {
- mWHITESPACE();
-
-
- }
- break;
- case 5 :
- // /private/prg/code/xreate/antlr/lisp.g:1:36: WORD
- {
- mWORD();
-
-
- }
- break;
-
- }
-
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/xreate/grammatic/lisp/LispParser.java b/src/main/java/org/xreate/grammatic/lisp/LispParser.java
deleted file mode 100644
index 19d8dea..0000000
--- a/src/main/java/org/xreate/grammatic/lisp/LispParser.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.xreate.grammatic.lisp;
-
-// $ANTLR 3.4 /private/prg/code/xreate/antlr/lisp.g 2012-04-07 17:57:03
-
-import org.antlr.runtime.*;
-import java.util.Stack;
-import java.util.List;
-import java.util.ArrayList;
-
-@SuppressWarnings({"all", "warnings", "unchecked"})
-public class LispParser extends Parser {
- public static final String[] tokenNames = new String[] {
- "<invalid>", "<EOR>", "<DOWN>", "<UP>", "WHITESPACE", "WORD", "'('", "')'", "','"
- };
-
- public static final int EOF=-1;
- public static final int T__6=6;
- public static final int T__7=7;
- public static final int T__8=8;
- public static final int WHITESPACE=4;
- public static final int WORD=5;
-
- // delegates
- public Parser[] getDelegates() {
- return new Parser[] {};
- }
-
- // delegators
-
-
- public LispParser(TokenStream input) {
- this(input, new RecognizerSharedState());
- }
- public LispParser(TokenStream input, RecognizerSharedState state) {
- super(input, state);
- }
-
- public String[] getTokenNames() { return LispParser.tokenNames; }
- public String getGrammarFileName() { return "/private/prg/code/xreate/antlr/lisp.g"; }
-
-
-
- // $ANTLR start "statement"
- // /private/prg/code/xreate/antlr/lisp.g:7:1: statement : WORD ( '(' statement ( ',' statement )* ')' )? ;
- public final ASTLispNode statement(ASTLispNode node) throws RecognitionException {
- try {
- // /private/prg/code/xreate/antlr/lisp.g:8:2: ( WORD ( '(' statement ( ',' statement )* ')' )? )
- // /private/prg/code/xreate/antlr/lisp.g:8:4: WORD ( '(' statement ( ',' statement )* ')' )?
- {
- CommonToken token = (CommonToken) match(input,WORD,FOLLOW_WORD_in_statement71);
-
- String text = token.getText();
- ASTLispNode nodeChild = ('0' <= text.charAt(0) && '9'>= text.charAt(0))? new ASTLispConstantNode(text) : new ASTLispNode(text);
- if (node != null){
- node.add(nodeChild);
- }
- node = nodeChild;
-
- // /private/prg/code/xreate/antlr/lisp.g:8:9: ( '(' statement ( ',' statement )* ')' )?
- int alt2=2;
- int LA2_0 = input.LA(1);
-
- if ( (LA2_0==6) ) {
- alt2=1;
- }
- switch (alt2) {
- case 1 :
- // /private/prg/code/xreate/antlr/lisp.g:8:10: '(' statement ( ',' statement )* ')'
- {
- match(input,6,FOLLOW_6_in_statement74);
-
- pushFollow(FOLLOW_statement_in_statement76);
- statement(node);
-
- state._fsp--;
-
-
- // /private/prg/code/xreate/antlr/lisp.g:8:24: ( ',' statement )*
- loop1:
- do {
- int alt1=2;
- int LA1_0 = input.LA(1);
-
- if ( (LA1_0==8) ) {
- alt1=1;
- }
-
-
- switch (alt1) {
- case 1 :
- // /private/prg/code/xreate/antlr/lisp.g:8:25: ',' statement
- {
- match(input,8,FOLLOW_8_in_statement79);
-
- pushFollow(FOLLOW_statement_in_statement81);
- statement(node);
-
- state._fsp--;
-
-
- }
- break;
-
- default :
- break loop1;
- }
- } while (true);
-
-
- match(input,7,FOLLOW_7_in_statement85);
-
- }
- break;
-
- }
-
-
- }
-
- }
- catch (RecognitionException re) {
- reportError(re);
- recover(input,re);
- }
-
- finally {
- // do for sure before leaving
- }
- return node;
- }
- // $ANTLR end "statement"
-
- // Delegated rules
-
-
-
-
- public static final BitSet FOLLOW_WORD_in_statement71 = new BitSet(new long[]{0x0000000000000042L});
- public static final BitSet FOLLOW_6_in_statement74 = new BitSet(new long[]{0x0000000000000020L});
- public static final BitSet FOLLOW_statement_in_statement76 = new BitSet(new long[]{0x0000000000000180L});
- public static final BitSet FOLLOW_8_in_statement79 = new BitSet(new long[]{0x0000000000000020L});
- public static final BitSet FOLLOW_statement_in_statement81 = new BitSet(new long[]{0x0000000000000180L});
- public static final BitSet FOLLOW_7_in_statement85 = new BitSet(new long[]{0x0000000000000002L});
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/xreate/ASTTest1.java b/src/test/java/org/xreate/ASTTest1.java
deleted file mode 100644
index c30c808..0000000
--- a/src/test/java/org/xreate/ASTTest1.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.xreate;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Maps;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class ASTTest1
- extends TestCase
-{
- /**
- * Create the test case
- *
- * @param testName name of the test case
- */
- public ASTTest1( String testName )
- {
- super( testName );
- }
-
- /**
- * @return the suite of tests being tested
- */
- public static Test suite()
- {
- return new TestSuite( ASTTest1.class );
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testAST1() throws NoSuchMethodException, IllegalAccessException, Throwable
- {
- ASTVar x = new ASTVar();
- ASTValue y = new ASTValue(10);
- ASTAssignment as = new ASTAssignment();
-
- as.var = x;
- as.value = y;
- ComputableAnalysis analysis = new ComputableAnalysis();
- ASTNode result = as.acceptComputableVisitor(analysis);
-
- assertTrue( true );
- }
-}
-
-
-
diff --git a/src/test/java/org/xreate/LispTest.java b/src/test/java/org/xreate/LispTest.java
deleted file mode 100644
index e9f7bc1..0000000
--- a/src/test/java/org/xreate/LispTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.xreate;
-
-import java.io.IOException;
-import junit.framework.TestCase;
-import org.antlr.runtime.*;
-import org.junit.Ignore;
-import org.xreate.grammatic.lisp.ASTLispNode;
-import org.xreate.grammatic.lisp.LispLexer;
-import org.xreate.grammatic.lisp.LispParser;
-
-import static org.junit.Assert.*;
-import org.junit.Test;
-import org.xreate.grammatic.lisp.LispInterpreter;
-/**
- *
- * @author pgess
- */
-public class LispTest {
- static int z;
-
- @Ignore
- @Test
- public void test1() throws RecognitionException{
- assertTrue(true);
-
- ANTLRStringStream in = new ANTLRStringStream("aa(bb, cc(dd, ee))");
-
- Lexer l = new LispLexer(in);
- CommonTokenStream tokens = new CommonTokenStream(l);
-
- LispParser p = new LispParser(tokens);
-
- ASTLispNode node = p.statement(null);
-
- int x = 0;
- }
-
- @Ignore
- @Test
- public void test2() throws IOException, RecognitionException{
- ANTLRStringStream in = new ANTLRFileStream("/private/prg/code/xreate/scripts/opcode.li");
-
- Lexer l = new LispLexer(in);
- CommonTokenStream tokens = new CommonTokenStream(l);
-
- LispParser p = new LispParser(tokens);
-
- ASTLispNode node = p.statement(null);
-
- int x = 0;
- }
-
- @Test
- public void test3() throws Exception{
- LispInterpreter lisp = new LispInterpreter();
-
- lisp.run("/private/prg/code/xreate/scripts/opcode.li");
-
- //assertEquals(answer, 100);
- }
-
- static {
- System.loadLibrary("jllvm");
- }
-}

Event Timeline