diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp index f22ebc1..eef0aae 100644 --- a/cpp/src/compilation/targetinterpretation.cpp +++ b/cpp/src/compilation/targetinterpretation.cpp @@ -1,626 +1,626 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * File: targetinterpretation.cpp * Author: pgess * * Created on June 29, 2016, 6:45 PM */ /** * \file targetinterpretation.h * \brief Interpretation support. See more details on [Interpretation](/d/concepts/interpretation/) */ #include "compilation/targetinterpretation.h" #include "pass/interpretationpass.h" #include "analysis/typeinference.h" #include "llvmlayer.h" #include "compilation/scopedecorators.h" #include "compilation/interpretation-instructions.h" #include #include #include using namespace std; using namespace xreate::compilation; namespace xreate{ namespace interpretation{ const Expression EXPRESSION_FALSE = Expression(Atom(0)); const Expression EXPRESSION_TRUE = Expression(Atom(1)); CodeScope* InterpretationScope::processOperatorIf(const Expression& expression) { const Expression& exprCondition = process(expression.getOperands()[0]); if (exprCondition == EXPRESSION_TRUE) { return expression.blocks.front(); } return expression.blocks.back(); } CodeScope* InterpretationScope::processOperatorSwitch(const Expression& expression) { const Expression& exprCondition = process(expression.operands[0]); bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT; //TODO check that one and only one case variant is appropriate for (size_t size = expression.operands.size(), i = flagHasDefault ? 2 : 1; i < size; ++i) { const Expression& exprCase = process(expression.operands[i]); if (function->getScope((const CodeScope*) exprCase.blocks.front())->processScope() == exprCondition) { return exprCase.blocks.back(); } } if (flagHasDefault) { const Expression& exprCaseDefault = expression.operands[1]; return exprCaseDefault.blocks.front(); } assert(false && "Switch has no appropriate variant"); return nullptr; } CodeScope* InterpretationScope::processOperatorSwitchVariant(const Expression& expression) { const Expression& condition = process(expression.operands.at(0)); assert(condition.op == Operator::VARIANT); const string& identCondition = expression.bindings.front(); Expression opExpected(Atom(condition.getValueDouble())); auto itFoundValue = std::find(++expression.operands.begin(), expression.operands.end(), opExpected); assert(itFoundValue != expression.operands.end()); int indexBlock = itFoundValue - expression.operands.begin() - 1; auto blockFound = expression.blocks.begin(); std::advance(blockFound, indexBlock); InterpretationScope* scopeI12n = function->getScope(*blockFound); if(condition.operands.size()) { const Expression& value = condition.operands.at(0); scopeI12n->overrideBindings({ {value, identCondition} }); } return *blockFound; } llvm::Value* InterpretationScope::processLate(const InterpretationOperator& op, const Expression& expression, const Context& context) { switch(op) { case IF_INTERPRET_CONDITION: { CodeScope* scopeResult = processOperatorIf(expression); llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile(); return result; } case SWITCH_INTERPRET_CONDITION: { CodeScope* scopeResult = processOperatorSwitch(expression); llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile(); return result; } case SWITCH_VARIANT: { CodeScope* scopeResult = processOperatorSwitchVariant(expression); const Expression& condition = expression.operands.at(0); const Expression& valueCondition = process(condition); const string identCondition = expression.bindings.front(); auto scopeCompilation = Decorators::getInterface(context.function->getScopeUnit(scopeResult)); if(valueCondition.operands.size()) { //override value Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult}; scopeCompilation->overrideDeclarations({ {symbCondition, Expression(valueCondition.operands.at(0))}} ); //set correct type for binding: TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast); int conditionIndex = valueCondition.getValueDouble(); ScopedSymbol symbolInternal = scopeResult->getSymbol(identCondition); scopeResult->__declarations[symbolInternal].bindType(typeVariant.__operands.at(conditionIndex)); } llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile(); return result; } case SWITCH_LATE: { latereasoning::LateReasoningCompiler compiler(dynamic_cast(this->function), context); return compiler.processSwitchLateStatement(expression, ""); } case FOLD_INTERPRET_INPUT: { //initialization const Expression& exprInput = process(expression.getOperands()[0]); assert(exprInput.op == Operator::LIST); CodeScope* scopeBody = expression.blocks.front(); const string& nameEl = expression.bindings[0]; Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody}; const std::string& idAccum = expression.bindings[1]; llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]); InterpretationScope* intrBody = function->getScope(scopeBody); auto unitBody = Decorators::getInterface(context.function->getScopeUnit(scopeBody)); const std::vector elementsInput = exprInput.getOperands(); for(size_t i = 0; i < elementsInput.size(); ++i) { const Expression& exprElement = elementsInput[i]; intrBody->overrideBindings({ {exprElement, nameEl} }); unitBody->overrideDeclarations({ {symbEl, exprElement} }); //resets unitBody unitBody->bindArg(rawAccum, string(idAccum)); rawAccum = unitBody->compile(); } return rawAccum; } // case FOLD_INF_INTERPRET_INOUT: // { // } //TODO refactor as InterpretationCallStatement class case CALL_INTERPRET_PARTIAL: { const std::string &calleeName = expression.getValueString(); ICodeScopeUnit* scopeUnitSelf = context.scope; ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName); const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee); std::vector argsActual; PIFSignature sig; sig.declaration = callee; for(size_t no = 0, size = expression.operands.size(); no < size; ++no) { const Expression& op = expression.operands[no]; if (calleeData.signature.at(no) == INTR_ONLY) { sig.bindings.push_back(process(op)); continue; } argsActual.push_back(scopeUnitSelf->process(op)); } TargetInterpretation* man = dynamic_cast (this->function->man); PIFunction* pifunction = man->getFunction(move(sig)); llvm::Function* raw = pifunction->compile(); boost::scoped_ptr statement(new BruteFnInvocation(raw, man->pass->man->llvm)); return (*statement)(move(argsActual)); } case QUERY_LATE: { return IntrinsicQueryInstruction( dynamic_cast(this->function)) .processLate(expression, context); } default: break; } assert(false && "Unknown late interpretation operator"); return nullptr; } llvm::Value* InterpretationScope::compile(const Expression& expression, const Context& context) { const InterpretationData& data = Attachments::get(expression); if (data.op != InterpretationOperator::NONE) { return processLate(data.op, expression, context); } Expression result = process(expression); return context.scope->process(result); } Expression InterpretationScope::process(const Expression& expression) { #ifndef NDEBUG if (expression.tags.count("bpoint")) { std::raise(SIGINT); } #endif PassManager* man = (static_cast (function->man))->pass->man; switch (expression.__state) { case Expression::INVALID: assert(false); case Expression::NUMBER: case Expression::STRING: return expression; case Expression::IDENT: { Symbol s = Attachments::get(expression); return Parent::processSymbol(s); } case Expression::COMPOUND: break; default: assert(false); } switch (expression.op) { case Operator::EQU: { const Expression& left = process(expression.operands[0]); const Expression& right = process(expression.operands[1]); if (left == right) return EXPRESSION_TRUE; return EXPRESSION_FALSE; } case Operator::NE: { const Expression& left = process(expression.operands[0]); const Expression& right = process(expression.operands[1]); if (left == right) return EXPRESSION_FALSE; return EXPRESSION_TRUE; } case Operator::LOGIC_AND: { assert(expression.operands.size() == 1); return process (expression.operands[0]); } // case Operator::LOGIC_OR: case Operator::CALL: { const std::string &fnName = expression.getValueString(); ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName); InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst); vector args; args.reserve(expression.getOperands().size()); for(size_t i = 0, size = expression.getOperands().size(); i < size; ++i) { args.push_back(process(expression.getOperands()[i])); } return fnUnit->process(args); } case Operator::CALL_INTRINSIC: { assert(false && "Unknown intrinsic"); } case Operator::QUERY: { return IntrinsicQueryInstruction(dynamic_cast(this->function)) .process(expression); } case Operator::QUERY_LATE: { assert(false && "Can't be interpretated"); return Expression(); } case Operator::IF: { CodeScope* scopeResult = processOperatorIf(expression); return function->getScope(scopeResult)->processScope(); } case Operator::SWITCH: { CodeScope* scopeResult = processOperatorSwitch(expression); return function->getScope(scopeResult)->processScope(); } case Operator::SWITCH_VARIANT: { CodeScope* scopeResult = processOperatorSwitchVariant(expression); return function->getScope(scopeResult)->processScope(); } case Operator::VARIANT: { if(!expression.operands.size()) return expression; Expression variantData = process(expression.operands[0]); Expression result{Operator::VARIANT, {variantData}}; result.setValueDouble(expression.getValueDouble()); return result; } case Operator::INDEX: { Expression exprData = process(expression.operands[0]); for (size_t keyId = 1; keyId < expression.operands.size(); ++keyId) { const Expression& exprKey = process(expression.operands[keyId]); if (exprKey.__state == Expression::STRING) { const string& key = exprKey.getValueString(); assert(exprData.__indexBindings.count(key)); size_t idxKey = exprData.__indexBindings.at(key); exprData = Expression(exprData.operands.at(idxKey)); continue; } if (exprKey.__state == Expression::NUMBER) { int key = exprKey.getValueDouble(); exprData = Expression(exprData.operands[key]); continue; } assert(false && "Inappropriate key"); } return exprData; } case Operator::FOLD: { const Expression& exprInput = process(expression.getOperands()[0]); const Expression& exprInit = process(expression.getOperands()[1]); const std::string& argEl = expression.bindings[0]; const std::string& argAccum = expression.bindings[1]; InterpretationScope* body = function->getScope(expression.blocks.front()); Expression accum = exprInit; for(size_t size = exprInput.getOperands().size(), i = 0; i < size; ++i) { body->overrideBindings({ {exprInput.getOperands()[i], argEl}, {accum, argAccum} }); accum = body->processScope(); } return accum; } case Operator::LIST: case Operator::LIST_RANGE: { Expression result(expression.op,{}); result.operands.resize(expression.operands.size()); result.bindings = expression.bindings; result.__indexBindings = expression.__indexBindings; int keyId = 0; for(const Expression& opCurrent : expression.operands) { result.operands[keyId++] = process(opCurrent); } return result; } // case Operator::MAP: { // break; // } default: break; } return expression; } InterpretationFunction* TargetInterpretation::getFunction(IFunctionUnit* unit) { if (__dictFunctionsByUnit.count(unit)) { return __dictFunctionsByUnit.at(unit); } InterpretationFunction* f = new InterpretationFunction(unit->function, this); __dictFunctionsByUnit.emplace(unit, f); assert(__functions.emplace(unit->function.id(), f).second); return f; } PIFunction* TargetInterpretation::getFunction(PIFSignature&& sig) { auto f = __pifunctions.find(sig); if (f != __pifunctions.end()) { return f->second; } PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this); __pifunctions.emplace(move(sig), result); assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second); return result; } InterpretationScope* TargetInterpretation::transformContext(const Context& c) { return this->getFunction(c.function)->getScope(c.scope->scope); } llvm::Value* TargetInterpretation::compile(const Expression& expression, const Context& ctx) { return transformContext(ctx)->compile(expression, ctx); } InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target* target) : Function(function, target) { } Expression InterpretationFunction::process(const std::vector& args) { InterpretationScope* body = getScope(__function->__entry); list> bindings; for(size_t i = 0, size = args.size(); i < size; ++i) { bindings.push_back(make_pair(args.at(i), body->scope->__bindings.at(i))); } body->overrideBindings(bindings); return body->processScope(); } // Partial function interpretation typedef BasicFunctionUnit PIFunctionUnitParent; class PIFunctionUnit : public PIFunctionUnitParent{ public: PIFunctionUnit(ManagedFnPtr f, std::set&& arguments, size_t id, CompilePass* p) : PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) { } protected: std::vector prepareSignature() override { LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm; AST* ast = PIFunctionUnitParent::pass->man->root; CodeScope* entry = PIFunctionUnitParent::function->__entry; std::vector signature; for(size_t no : argumentsActual) { VNameId argId = entry->__identifiers.at(entry->__bindings.at(no)); ScopedSymbol arg{argId, versions::VERSION_NONE}; signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type))); } return signature; } llvm::Function::arg_iterator prepareBindings() override{ CodeScope* entry = PIFunctionUnitParent::function->__entry; ICodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry); llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin(); for(size_t no : argumentsActual) { ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), versions::VERSION_NONE}; entryCompilation->bindArg(&*fargsI, arg); fargsI->setName(entry->__bindings.at(no)); ++fargsI; } return fargsI; } virtual std::string prepareName() override { return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id); } private: std::set argumentsActual; size_t __id; } ; PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target) : InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) { const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration); std::set argumentsActual; for (size_t no = 0, size = functionData.signature.size(); no < size; ++no) { if (functionData.signature.at(no) != INTR_ONLY) { argumentsActual.insert(no); } } functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass); CodeScope* entry = signatureInstance.declaration->__entry; auto entryUnit = Decorators::getInterface<>(functionUnit->getEntry()); InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry); list> bindingsPartial; list> declsPartial; for(size_t no = 0, sigNo = 0, size = entry->__bindings.size(); no < size; ++no) { if(functionData.signature.at(no) == INTR_ONLY) { bindingsPartial.push_back({signatureInstance.bindings[sigNo], entry->__bindings[no]}); VNameId argId = entry->__identifiers.at(entry->__bindings[no]); Symbol argSymbol{ScopedSymbol {argId, versions::VERSION_NONE}, entry}; declsPartial.push_back({argSymbol, signatureInstance.bindings[sigNo]}); ++sigNo; } } entryIntrp->overrideBindings(bindingsPartial); entryUnit->overrideDeclarations(declsPartial); } llvm::Function* PIFunction::compile() { llvm::Function* raw = functionUnit->compile(); return raw; } bool operator<(const PIFSignature& lhs, const PIFSignature& rhs) { if (lhs.declaration.id() != rhs.declaration.id()) { return lhs.declaration.id() < rhs.declaration.id(); } return lhs.bindings < rhs.bindings; } bool operator<(const PIFSignature& lhs, PIFunction * const rhs) { return lhs < rhs->signatureInstance; } bool operator<(PIFunction * const lhs, const PIFSignature& rhs) { return lhs->signatureInstance < rhs; } } } /** \class xreate::interpretation::InterpretationFunction * * Holds list of xreate::interpretation::InterpretationScope 's focused on interpretation of individual code scopes * * There is particulat subclass PIFunction intended to represent partially interpreted functions. - *\sa TargetInterpretation, [Interpretation Concept](/w/concepts/dfa) + *\sa TargetInterpretation, [Interpretation Concept](/d/concepts/interpretation/) */ /** \class xreate::interpretation::TargetInterpretation * * TargetInterpretation is executed during compilation and is intended to preprocess eligible for interpretation parts of a source code. * * Keeps a list of InterpretationFunction / PIFunction that represent interpretation for an individual functions. * * There is \ref InterpretationScopeDecorator that embeds interpretation to an overall compilation process. * \sa InterpretationPass, compilation::Target, [Interpretation Concept](/d/concepts/interpretation/) * */ diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h index e95cc7d..7765645 100644 --- a/cpp/src/query/containers.h +++ b/cpp/src/query/containers.h @@ -1,96 +1,96 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Author: pgess * * containers.h * Created on 3/14/15. */ /** * \file query/containers.h - * \brief Transcend solutions on [Containers](/w/concepts/containers) implementation details + * \brief Transcend solutions on [Containers](/d/concepts/containers/) implementation details */ #ifndef _XREATE_CONTAINERSQUERY_H_ #define _XREATE_CONTAINERSQUERY_H_ #include "xreatemanager.h" #include "transcendlayer.h" #include namespace xreate { namespace containers { enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST}; template struct ImplementationRec; template<> struct ImplementationRec { size_t size; }; template<> struct ImplementationRec{ Symbol source; }; struct Implementation; struct ImplementationLinkedList { bool flagIsValid; std::string fieldPointer; Expression terminator; ImplementationLinkedList(const Symbol& source); operator bool() const; Implementation getImplementationData() const; private: Symbol s; }; struct Implementation { typedef boost::variant, ImplementationRec> Variant; ImplementationType impl; Variant data; static Implementation create(const Symbol &var); static Implementation create(const Symbol& var, const std::string &implSerialized); template const ImplementationRec& extract() const{ const ImplementationRec& rec = boost::get>(data); return rec; } }; /** * \brief Queries Transcend solutions on containers implementation details * \sa xreate::containers::Iterator */ class Query : public xreate::IQuery { public: static Implementation queryImplementation(xreate::Symbol const &s); void init(TranscendLayer* transcend); Query(); ~Query(){} private: bool flagDataIsLoaded = false; PassManager *man; }; } template<> struct AttachmentsDict { typedef containers::Implementation Data; static const unsigned int key = 1; }; } #endif //_XREATE_CONTAINERSQUERY_H_ diff --git a/documentation-api/namespaces.dox b/documentation-api/namespaces.dox index 1de792c..9428052 100644 --- a/documentation-api/namespaces.dox +++ b/documentation-api/namespaces.dox @@ -1,44 +1,41 @@ /** - * \namespace xreate - * \brief Aww - * * \namespace xreate::cfa * \brief The CFA(Control Flow Analysis) related functionality * * \namespace xreate::dfa * \brief The DFA(Data Flow Analysis) related functionality * * \namespace xreate::interpretation * \brief Interpretation support * * \namespace xreate::typeinference * \brief Type inference support * * \namespace xreate::analysis * \brief The analysis' internal routines * * \namespace xreate::pointerarithmetic * \brief Pointer arithemitic support * * \namespace xreate::compilation * \brief The compilation internals used by \ref CompilePass * * \namespace xreate::polymorph * \brief Polymorphism support * * \namespace xreate::latex * \brief Latex(Late Context) support * * \namespace xreate::latereasoning * \brief Late Transcend support * * \namespace xreate::versions * \brief Versioned variables support. See the [explanation](/d/concepts/versions/) * * \namespace xreate::containers * \brief Containers support. See [the explanation](/d/concepts/containers/) * * \namespace xreate::modules * \brief Modules support * */