polymorph.h
No OneTemporary

File Metadata

Created
Fri, Mar 13, 10:07 PM

polymorph.h

/*
* 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 <v.melnychenko@xreate.org>
*
* Created on October 7, 2017
*/
/**
* \file src/compilation/polymorph.h
* \brief Polymorphism-aware compilation routines
*/
#ifndef POLYMORPHCOMPILER_H
#define POLYMORPHCOMPILER_H
#include "pass/compilepass.h"
#include "query/polymorph.h"
#include "compilation/latetranscend.h"
#include "compilation/targetinterpretation.h"
#include "analysis/utils.h"
#include "aux/expressions.h"
namespace xreate{
namespace polymorph{
//typedef Expression Selector;
/** \brief An instance of \ref compilation::IFnInvocation to manage polymorphic functions invocation*/
//class PolymorphFnInvocation: public compilation::IFnInvocation{
//public:
// PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
// std::list<ManagedFnPtr> calleeSpecializations,
// CompilePass* pass,
// PolymorphQuery* query,
// LLVMLayer* llvm,
// latereasoning::LateReasoningCompiler* compiler);
//
// llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
//
//private:
// latereasoning::LateAnnotation __selector;
// std::list<ManagedFnPtr> __calleeSpecializations;
//
// CompilePass* __pass;
// PolymorphQuery* __query;
// LLVMLayer* __llvm;
// latereasoning::LateReasoningCompiler* __compiler;
//} ;
/**
* \brief Polymorphism aware \ref xreate::compilation::IBruteScope decorator
* \implements xreate::compilation::IBruteScope
*/
bool isFnGuarded(const std::string& fn, const AST& root);
template <class Parent>
class PolymorphBruteScopeDecorator: public Parent{
public:
PolymorphBruteScopeDecorator(const CodeScope * const codeScope,
compilation::IBruteFunction* f,
CompilePass* compilePass)
: Parent(codeScope, f, compilePass){ }
protected:
compilation::IFnInvocation*
findFunction(const Expression& opCall) override{
LLVMLayer* llvm = Parent::pass->man->llvm;
AST* ast = Parent::pass->man->root;
TranscendLayer* transcend = Parent::pass->man->transcend;
//Check does invocation require guards satisfaction
const std::string& calleeName = opCall.getValueString();
if(!isFnGuarded(calleeName, *ast)){
return Parent::findFunction(opCall);
}
//Several specializations
PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (
Parent::pass->man->transcend->getQuery(QueryId::PolymorphQuery));
//Fill up a dict of all possible specializations
const std::list<ManagedFnPtr>& specs = ast->getFnSpecializations(calleeName);
std::map<std::string, ManagedFnPtr> dictSpecializations;
for(ManagedFnPtr specFn : specs) {
const TypeAnnotation& specT = specFn->guard.type;
assert(specFn->guard.isValid());
assert(specT.__operator == TypeOperator::VARIANT);
unsigned int variantId = specFn->guard.getValueDouble();
std::string specStr = specT.fields.at(variantId);
dictSpecializations.emplace(specStr, specFn);
}
auto supply = query->getFnSupply(ASTSite{opCall.id});
Gringo::Symbol supplyRaw = std::get<0>(supply);
ExpandedType supplyT = std::get<1>(supply);
Expression supplyE = analysis::representTransExpression(supplyRaw, supplyT, transcend);
const std::string& specStr = supplyT->fields.at(supplyE.getValueDouble());
ManagedFnPtr specFn = dictSpecializations.at(specStr);
const ExpandedType supplyDataT = ast->expandType(supplyT->__operands.at(supplyE.getValueDouble()));
compilation::BruteFnInvocation* fnInvocDefault = new compilation::BruteFnInvocation(
Parent::pass->getBruteFn(specFn)->compile(), llvm
);
if (!supplyDataT->isValid()){
return fnInvocDefault;
}
const Expression& supplyDataE = getVariantData(supplyE, supplyT);
llvm::Value* supplyDataRaw = Parent::process(supplyDataE);
return new compilation::HiddenArgsFnInvocation({supplyDataRaw}, fnInvocDefault);
}
} ;
template <class Parent>
class PolymorphBruteFnDecorator: public Parent{
public:
PolymorphBruteFnDecorator(ManagedFnPtr f, CompilePass *p): Parent(f, p){}
protected:
std::vector<llvm::Type *>
prepareSignature() override {
std::vector<llvm::Type *> &&signature = Parent::prepareSignature();
if (!Parent::function->guard.isValid()) return signature;
AST* ast = Parent::pass->man->root;
unsigned int guardDataId = signature.size() + 1;
const Expression& guardE = Parent::function->guard;
assert(guardE.op == Operator::VARIANT);
const ExpandedType guardT = ast->expandType(guardE.type.__operands.at(guardE.getValueDouble()));
if (!guardT->isValid()) return signature;
if (!guardE.bindings.size()) return signature;
assert(guardE.bindings.size() == 1);
std::string guardArgName = guardE.bindings.at(0);
llvm::Type *guardTRaw = Parent::pass->man->llvm->toLLVMType(guardT);
Expression argBindE;
argBindE.type = guardT;
Parent::function->addBinding(
Atom<Identifier_t>(std::move(guardArgName)),
std::move(argBindE),
guardDataId
);
signature.push_back(guardTRaw);
return signature;
}
};
}
} //end of xreate::polymorph
#endif /* POLYMORPHCOMPILER_H */

Event Timeline